神奇好望角 The Magical Cape of Good Hope

          庸人不必自擾,智者何需千慮?
          posts - 26, comments - 50, trackbacks - 0, articles - 11
            BlogJava :: 首頁 ::  :: 聯系 :: 聚合  :: 管理

          非主流并發工具之 CountDownLatch

          Posted on 2011-10-14 14:22 蜀山兆孨龘 閱讀(1716) 評論(1)  編輯  收藏 所屬分類: Java SE

          顧名思義,CountDownLatch 是一個用來倒計數的咚咚。如果某項任務可以拆分成若干個子任務同時進行,然后等待所有的子任務完成,可以考慮使用它。

          該類的用法非常簡單。首先構造一個 CountDownLatch,唯一的參數是任務數量,一旦構造完畢就不能修改。接著啟動所有的子任務(線程),且每個子任務在完成自己的計算后,調用 CountDownLatch#countDown 方法將倒計數減一。最后在主線程中調用 CountDownLatch#await 方法等待計數器歸零。

          例如賽跑的準備階段,八名運動員先后到達起點做好準備,然后裁判打響發令槍,準備工作就結束了,比賽開始。如果把從運動員就位到發令槍響看做賽跑準備任務,那么每個運動員的準備過程就是其子任務,可以用 CountDownLatch 模擬如下:

                  final int count = 8;
                  System.out.println("運動員開始就位。");
          
                  // 構造 CountDownLatch。
                  final CountDownLatch cdl = new CountDownLatch(count);
                  for (int i = 1; i <= count; i++) {
                      final int number = i;
                      new Thread() {
                          @Override
                          public void run() {
                              System.out.println(number + " 號運動員到場并開始準備...");
                              try {
                                  // 讓運動員隨機準備 2~5 秒鐘。
                                  TimeUnit.SECONDS.sleep(new Random().nextInt(4) + 2);
                              } catch (InterruptedException ex) {
                              }
                              System.out.println(number + " 號運動員就位。");
                              // 倒計數減一。
                              cdl.countDown();
                          }
                      }.start();
                  }
          
                  System.out.println("等待所有運動員就位...");
                  try {
                      // 等待倒計數變為 0。
                      cdl.await();
                      System.out.println("比賽開始。");
                  } catch (InterruptedException ex) {
                  }
              

          運行輸出(可能)為:

          運動員開始就位。
          1 號運動員到場并開始準備...
          2 號運動員到場并開始準備...
          4 號運動員到場并開始準備...
          等待所有運動員就位...
          8 號運動員到場并開始準備...
          6 號運動員到場并開始準備...
          3 號運動員到場并開始準備...
          7 號運動員到場并開始準備...
          5 號運動員到場并開始準備...
          6 號運動員就位。
          1 號運動員就位。
          5 號運動員就位。
          4 號運動員就位。
          7 號運動員就位。
          8 號運動員就位。
          2 號運動員就位。
          3 號運動員就位。
          比賽開始。

          從上面的例子還可以看出 CountDownLatch 的局限性和 CompletionService 類似,在于無法處理子任務數量不確定的情況,例如統計某個文件夾中的文件數量。另外,如果某個子任務在調用 countDown 之前就掛掉了,倒計數就永遠不會歸零。對于這種情況,要么用 finally 之類的手段保證 countDown 一定會被調用,要么用帶參數的 await 方法指定超時時間。


          評論

          # re: 非主流并發工具之 CountDownLatch  回復  更多評論   

          2011-10-14 20:56 by 與你同飛
          謝謝,長見識了。
          主站蜘蛛池模板: 锦州市| 丹棱县| 辽宁省| 长宁县| 南皮县| 顺义区| 兴安盟| 土默特左旗| 松潘县| 荔浦县| 应城市| 遵化市| 新疆| 吉木萨尔县| 化德县| 城固县| 井冈山市| 喀喇| 开封市| 永平县| 绥棱县| 城固县| 镇赉县| 平阳县| 宜丰县| 永平县| 乐亭县| 绥中县| 项城市| 惠州市| 大足县| 布拖县| 贺兰县| 南溪县| 威海市| 同江市| 邯郸市| 元朗区| 金阳县| 衢州市| 通榆县|