J2EE學習筆記
          我們的失落……
          posts - 13,comments - 1,trackbacks - 0

          原文出處:http://blog.chenlb.com/2008/11/join-or-countdownlatch-make-main-thread-wait-all-sub-thread.html

          在編寫多線程的工作中,有個常見的問題:主線程(main) 啟動好幾個子線程(task)來完成并發任務,主線程要等待所有的子線程完成之后才繼續執行main的其它任務。
          默認主線程退出時其它子線程不會停,如果想讓main退出時其它子線程終止,可以用subThread.setDaemon(true) 設置子線程為“守護線程”。但現在要的是主線程等待所有子線程完成后,還要執行其它操作(比如:結果合并)。記得可以用join()方法來等待所有子線程完成后,才繼續執行。如果不用join(),main線程與子線程是并發的,要稍加處理使main線程暫停。簡單點用Thread.sleep(long millis) 了,當然用“等待-通知”機制也可以。
          下面是用join的實現main等待所有子線程完成了,示例代碼:WaitAllSubThread.java。

          package com.chenlb;   
            
          import java.util.Random;   
            
          /**  
           * 
          @author chenlb 2008-11-1 下午11:32:43  
           
          */
            
          public class WaitAllSubThread {   
            
              
          /*int liveThreadNum;//記錄運行的子線程數  
              
          */
            
              
          int n;  //工作線程數   
            
              
          public WaitAllSubThread(int n) {   
                  
          this.n = n;   
              }
             
            
              
          class Worker implements Runnable {   
            
                  String name;   
                  
          int sleep;   
            
                  
          public Worker(String name, int sleep) {   
                      
          this.name = name;   
                      
          this.sleep = sleep;   
                  }
             
            
                  
          public void run() {   
                      
          /*upLive(); //計算此線程已經工作.  
                      
          */
            
                      System.out.println(name
          +", start to work.");   
                      
          try {   
                          Thread.sleep(sleep);    
          //虛擬工作. 10s 隨機時間   
                      }
           catch (InterruptedException e) {   
                          System.out.println(name
          +" interrupted.");   
                      }
             
                      System.out.println(name
          +", end to work ["+sleep+"] sleep.");   
                      
          /*downLive();   //此線程工作完成  
                      
          */
            
                  }
             
              }
             
          /*  //記錄線程數的同步方法.  
              private synchronized void downLive() {  
                  liveThreadNum--;  
              }  
           
              private synchronized void upLive() {  
                  liveThreadNum++;  
              }  
           
              private synchronized boolean isLive() {  
                  return liveThreadNum > 0;  
              }
          */
            
            
              
          public void run() {   
                  System.out.println(
          "-------------main run start-------------");   
                  
          int sleepSaid = 10 * 1000;  //每個工作線程虛擬工作最大時間   
                  Random rm = new Random();   
                  
          for(int i=0; i<ths.length; i++{   
                      ths[i] 
          = new Thread(new MyTask(rm.nextInt(sleep)+1));   
            
                      ths[i].start();   
                  }
             
            
                  
          for(Thread th : ths) {   
                      
          try {   
                          th.join();
          //join方式   
                      }
           catch (InterruptedException e) {   
                          
          // TODO Auto-generated catch block   
                          e.printStackTrace();   
                      }
             
                  }
             
                  
          /*//等待所有工作線程完成.  
                  while(isLive()) {  
                      try {  
                          Thread.sleep(1000); //每隔1s查看下是否所有線程完成.  
                      } catch (InterruptedException e) {  
                          System.out.println("main thread sleep interrupted.");  
                      }  
                  }
          */
            
                  System.out.println(
          "---------------main run end--------------");   
              }
             
            
              
          public static void main(String[] args) {   
                  WaitAllSubThread wast 
          = new WaitAllSubThread(10);   
                  wast.run();   
              }
             
          }


          如果不用join,上面的代碼會使先輸出“main run end”,原因是:main 與 所有sub thread并發工作,不等待所有子線程繼續工作。而所有子線程完成了,main線程才會退出。
          用比較笨的方式:把上面/* */的注釋去掉,把 th.join();塊注釋掉。這樣可以使等待所有子線程完成了才去執行其它后續的(比如:這里是輸出“main run end”)。分析:程序中加工作的子線程的計數(liveThreadNum)。main不斷輪詢是否所有子線程完成,所有完成就執行剩下的。
          上面的是昨天寫的,今天發現一個更加簡潔的方式去處理main線程阻塞(等待所有子線程),那就是java.util.concurrent.CountDownLatch類。現在重新實現上面的功能,CountDownLatchUse.java

          package com.chenlb;   
            
          import java.util.Random;   
          import java.util.concurrent.CountDownLatch;   
            
          /**  
           * 
          @author chenlb 2008-11-1 下午11:43:31  
           
          */
            
          public class CountDownLatchUse {   
            
              
          final CountDownLatch downLatch;   
              
          int n;  //工作線程數   
            
              
          public CountDownLatchUse(int n) {   
                  
          this.downLatch = new CountDownLatch(n);   
                  
          this.n = n;   
              }
             
            
              
          class Worker implements Runnable {   
            
                  String name;   
                  
          int sleep;   
            
                  
          public Worker(String name, int sleep) {   
                      
          this.name = name;   
                      
          this.sleep = sleep;   
                  }
             
            
                  
          public void run() {   
                      System.out.println(name
          +", start to work.");   
                      
          try {   
                          Thread.sleep(sleep);    
          //虛擬工作. 10s 隨機時間   
                      }
           catch (InterruptedException e) {   
                          System.out.println(name
          +" interrupted.");   
                      }
             
                      System.out.println(name
          +", end to work ["+sleep+"] sleep.");   
                      meDone();   
          //某個工作線程完成   
                  }
             
              }
             
            
              
          private void meDone() {   
                  downLatch.countDown();   
              }
             
            
              
          public void run() {   
                  System.out.println(
          "-------------main run start-------------");   
                  
          int sleepSaid = 10 * 1000;  //每個工作線程虛擬工作最大時間   
                  Random rm = new Random();   
                  
          for(int i=0; i<n; i++{   
                      
          new Thread(new Worker("worker-"+i, rm.nextInt(sleepSaid)+1)).start();   
                  }
             
            
                  
          try {   
                      downLatch.await();  
          //等待所有工作線程完成.   
                  }
           catch (InterruptedException e) {   
                      System.out.println(
          "main interrupted.");   
                  }
             
                  System.out.println(
          "---------------main run end--------------");   
              }
             
            
              
          public static void main(String[] args) {   
                  CountDownLatchUse mtu 
          = new CountDownLatchUse(10);   
                  mtu.run();   
              }
             
          }


          CountDownLatch.countDown();完成線程的計數。CountDownLatch.await();完成了主線程阻塞。簡潔就是好,以后就這種方式了。

          posted on 2010-01-26 18:00 J2EE學習筆記 閱讀(1207) 評論(0)  編輯  收藏 所屬分類: 轉載java
          主站蜘蛛池模板: 文成县| 青铜峡市| 洛隆县| 科尔| 灌云县| 广德县| 闽侯县| 高邮市| 绥棱县| 左云县| 博乐市| 平乡县| 澄迈县| 宁安市| 皮山县| 利辛县| 乌恰县| 淳安县| 九龙城区| 双峰县| 宁强县| 集贤县| 襄城县| 堆龙德庆县| 新营市| 高安市| 信阳市| 革吉县| 鄂伦春自治旗| 凤翔县| 新乐市| 马公市| 宁晋县| 秦皇岛市| 盘锦市| 阜平县| 米易县| 蓬莱市| 象山县| 革吉县| 项城市|