有兩種方法:
第一種方法:
一般情況,我們實現多線程都是Thread或者Runnable(后者比較多),但是,這兩種都是沒返回值的,所以我們需要使用callable(有返回值的多線程)和future(獲得線程的返回值)來實現了。
- /**
- * 假如有Thread1、Thread2、ThreaD3、Thread4四條線程分別統計C、D、E、F四個盤的大小,所有線程都統計完畢交給Thread5線程去做匯總,應當如何實現?
- */
- public class TestThread {
- public static void main(String[] args) {
- ThreadCount tc = null;
- ExecutorService es = Executors.newCachedThreadPool();//線程池
- CompletionService<Integer> cs = new ExecutorCompletionService<Integer>(es);
- for(int i=0;i<4;i++){
- tc = new ThreadCount(i+1);
- cs.submit(tc);
- }
- // 添加結束,及時shutdown,不然主線程不會結束
- es.shutdown();
- int total = 0;
- for(int i=0;i<4;i++){
- try {
- total+=cs.take().get();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
- System.out.println(total);
- }
- }
- class ThreadCount implements Callable<Integer>{
- private int type;
- ThreadCount(int type){
- this.type = type;
- }
- @Override
- public Integer call() throws Exception {
- if(type==1){
- System.out.println("C盤統計大小");
- return 1;
- }else if(type==2){
- Thread.sleep(20000);
- System.out.println("D盤統計大小");
- return 2;
- }else if(type==3){
- System.out.println("E盤統計大小");
- return 3;
- }else if(type==4){
- System.out.println("F盤統計大小");
- return 4;
- }
- return null;
- }
- }
ps:一個需要注意的小細節,cs.take.get()獲取返回值,是按照完成的順序的,即上面案例返回順序是CEFD
第二種方法:
第一種方法:
直接用join把線程5加入進去即可
第二種方法:
用Java.util.concurrent下的方法解決
用CountDownLatch : 一個線程(或者多個), 等待另外N個線程完成某個事情之后才能執行
CountDownLatch 是計數器, 線程完成一個就記一個, 就像 報數一樣, 只不過是遞減的.
一個例子如下:
- public class CountDownLatchDemo {
- final static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- public static void main(String[] args) throws InterruptedException {
- CountDownLatch latch=new CountDownLatch(2);//兩個工人的協作
- Worker worker1=new Worker("zhang san", 5000, latch);
- Worker worker2=new Worker("li si", 8000, latch);
- worker1.start();//
- worker2.start();//
- latch.await();//等待所有工人完成工作
- System.out.println("all work done at "+sdf.format(new Date()));
- }
- static class Worker extends Thread{
- String workerName;
- int workTime;
- CountDownLatch latch;
- public Worker(String workerName ,int workTime ,CountDownLatch latch){
- this.workerName=workerName;
- this.workTime=workTime;
- this.latch=latch;
- }
- public void run(){
- System.out.println("Worker "+workerName+" do work begin at "+sdf.format(new Date()));
- doWork();//工作了
- System.out.println("Worker "+workerName+" do work complete at "+sdf.format(new Date()));
- latch.countDown();//工人完成工作,計數器減一
- }
- private void doWork(){
- try {
- Thread.sleep(workTime);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
CyclicBarrier : N個線程相互等待,任何一個線程完成之前,所有的線程都必須等待。
這樣應該就清楚一點了,對於CountDownLatch來說,重點是那個“一個線程”, 是它在等待, 而另外那N的線程在把“某個事情”做完之后可以繼續等待,可以終止。而對於CyclicBarrier來說,重點是那N個線程,他們之間任何一個沒有完成,所有的線程都必須等待。CyclicBarrier更像一個水閘, 線程執行就想水流, 在水閘處都會堵住, 等到水滿(線程到齊)了, 才開始泄流.
