假如有Thread1、Thread2、ThreaD3、Thread4四條線程分別統計C、D、E、F四個盤的大小,所有線程都統計完畢交給Thread5線程去做匯總,應當如何實現?


有兩種方法:

  第一種方法:

  一般情況,我們實現多線程都是Thread或者Runnable(后者比較多),但是,這兩種都是沒返回值的,所以我們需要使用callable(有返回值的多線程)和future(獲得線程的返回值)來實現了。

 
  1. /** 
  2.  * 假如有Thread1、Thread2、ThreaD3、Thread4四條線程分別統計C、D、E、F四個盤的大小,所有線程都統計完畢交給Thread5線程去做匯總,應當如何實現? 
  3.  */  
  4. public class TestThread {  
  5.     public static void main(String[] args) {  
  6.         ThreadCount tc = null;  
  7.         ExecutorService es = Executors.newCachedThreadPool();//線程池  
  8.         CompletionService<Integer> cs = new ExecutorCompletionService<Integer>(es);  
  9.         for(int i=0;i<4;i++){  
  10.             tc = new ThreadCount(i+1);  
  11.             cs.submit(tc);  
  12.         }  
  13.           
  14.         // 添加結束,及時shutdown,不然主線程不會結束  
  15.         es.shutdown();  
  16.           
  17.         int total = 0;  
  18.         for(int i=0;i<4;i++){  
  19.             try {  
  20.                 total+=cs.take().get();  
  21.             } catch (InterruptedException e) {  
  22.                 e.printStackTrace();  
  23.             } catch (ExecutionException e) {  
  24.                 e.printStackTrace();  
  25.             }  
  26.         }  
  27.           
  28.         System.out.println(total);  
  29.     }  
  30. }  
  31.   
  32. class ThreadCount implements Callable<Integer>{  
  33.     private int type;  
  34.     ThreadCount(int type){  
  35.         this.type = type;  
  36.     }  
  37.     @Override  
  38.     public Integer call() throws Exception {  
  39.         if(type==1){  
  40.             System.out.println("C盤統計大小");  
  41.             return 1;  
  42.         }else if(type==2){  
  43.             Thread.sleep(20000);  
  44.             System.out.println("D盤統計大小");  
  45.             return 2;  
  46.         }else if(type==3){  
  47.             System.out.println("E盤統計大小");  
  48.             return 3;  
  49.         }else if(type==4){  
  50.             System.out.println("F盤統計大小");  
  51.             return 4;  
  52.         }  
  53.         return null;  
  54.     }  
  55. }  

ps:一個需要注意的小細節,cs.take.get()獲取返回值,是按照完成的順序的,即上面案例返回順序是CEFD

  第二種方法:

 

第一種方法:

 

直接用join把線程5加入進去即可

 

第二種方法:

 

Java.util.concurrent下的方法解決

 

用CountDownLatch : 一個線程(或者多個), 等待另外N個線程完成某個事情之后才能執行

 

CountDownLatch 是計數器, 線程完成一個就記一個, 就像 報數一樣, 只不過是遞減的.

 

一個例子如下:

 
  1. public class CountDownLatchDemo {      
  2.     final static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");      
  3.     public static void main(String[] args) throws InterruptedException {      
  4.         CountDownLatch latch=new CountDownLatch(2);//兩個工人的協作      
  5.         Worker worker1=new Worker("zhang san", 5000, latch);      
  6.         Worker worker2=new Worker("li si", 8000, latch);      
  7.         worker1.start();//      
  8.         worker2.start();//      
  9.         latch.await();//等待所有工人完成工作      
  10.         System.out.println("all work done at "+sdf.format(new Date()));      
  11.     }      
  12.           
  13.           
  14.     static class Worker extends Thread{      
  15.         String workerName;       
  16.         int workTime;      
  17.         CountDownLatch latch;      
  18.         public Worker(String workerName ,int workTime ,CountDownLatch latch){      
  19.              this.workerName=workerName;      
  20.              this.workTime=workTime;      
  21.              this.latch=latch;      
  22.         }      
  23.         public void run(){      
  24.             System.out.println("Worker "+workerName+" do work begin at "+sdf.format(new Date()));      
  25.             doWork();//工作了      
  26.             System.out.println("Worker "+workerName+" do work complete at "+sdf.format(new Date()));      
  27.             latch.countDown();//工人完成工作,計數器減一      
  28.       
  29.         }      
  30.               
  31.         private void doWork(){      
  32.             try {      
  33.                 Thread.sleep(workTime);      
  34.             } catch (InterruptedException e) {      
  35.                 e.printStackTrace();      
  36.             }      
  37.         }      
  38.     }      
  39.           
  40.            
  41. }   

 

 

CyclicBarrier        : N個線程相互等待,任何一個線程完成之前,所有的線程都必須等待。

這樣應該就清楚一點了,對於CountDownLatch來說,重點是那個“一個線程”, 是它在等待, 而另外那N的線程在把“某個事情”做完之后可以繼續等待,可以終止。而對於CyclicBarrier來說,重點是那N個線程,他們之間任何一個沒有完成,所有的線程都必須等待。CyclicBarrier更像一個水閘, 線程執行就想水流, 在水閘處都會堵住, 等到水滿(線程到齊)了, 才開始泄流.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM