神奇好望角 The Magical Cape of Good Hope

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

          非主流并發(fā)工具之 CountDownLatch

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

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

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

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

                  final int count = 8;
                  System.out.println("運動員開始就位。");
          
                  // 構(gòu)造 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 + " 號運動員就位。");
                              // 倒計數(shù)減一。
                              cdl.countDown();
                          }
                      }.start();
                  }
          
                  System.out.println("等待所有運動員就位...");
                  try {
                      // 等待倒計數(shù)變?yōu)?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 類似,在于無法處理子任務數(shù)量不確定的情況,例如統(tǒng)計某個文件夾中的文件數(shù)量。另外,如果某個子任務在調(diào)用 countDown 之前就掛掉了,倒計數(shù)就永遠不會歸零。對于這種情況,要么用 finally 之類的手段保證 countDown 一定會被調(diào)用,要么用帶參數(shù)的 await 方法指定超時時間。


          評論

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

          2011-10-14 20:56 by 與你同飛
          謝謝,長見識了。
          主站蜘蛛池模板: 禹州市| 西乌珠穆沁旗| 利津县| 姚安县| 焦作市| 城步| 抚远县| 武平县| 安福县| 青田县| 方正县| 黎城县| 左云县| 六枝特区| 丘北县| 濉溪县| 乌兰县| 汶上县| 台湾省| 宿松县| 渭源县| 阳江市| 珲春市| 榕江县| 句容市| 海南省| 绥江县| 彰武县| 高青县| 鹤庆县| 前郭尔| 松江区| 红安县| 丽江市| 广南县| 麻栗坡县| 巴中市| 玛多县| 酒泉市| 阳江市| 当涂县|