一、CountDownLatch:一個同步工具類,它容許一個或多個線程一直等待,直到其餘線程的操做執行完後再執行。html
二、ThreadPoolExecutor/ExecutorService:線程池,使用線程池能夠複用線程,下降頻繁建立線程形成的性能消耗,同時對線程的建立、啓動、中止、銷燬等操做更簡便。java
三、使用場景舉例:
年底公司組織團建,要求每一位員工週六上午8點到公司門口集合,統一乘坐公司所租大巴前往目的地。
在這個案例中,公司做爲主線程,員工做爲子線程。多線程
四、代碼示例:iphone
package com.test.thread;分佈式
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;ide
/**
* @author javaloveiphone
* @date 建立時間:2017年1月25日 上午10:59:11
* @Description:
*/
public class Company {
public static void main(String[] args) throws InterruptedException {工具
//員工數量
int count = 5;
//建立計數器
//構造參數傳入的數量值表明的是latch.countDown()調用的次數
CountDownLatch latch = new CountDownLatch(count);性能
//建立線程池,能夠經過如下方式建立
//ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1,1,60,TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>(count));
ExecutorService threadPool = Executors.newFixedThreadPool(count);this
System.out.println("公司發送通知,每一位員工在週六早上8點到公司大門口集合");
for(int i =0;i<count ;i++){
//將子線程添加進線程池執行
Thread.sleep(10);
threadPool.execute(new Employee(latch,i+1));
}
try {
//阻塞當前線程,直到全部員工到達公司大門口以後才執行
latch.await();
// 使當前線程在鎖存器倒計數至零以前一直等待,除非線程被中斷或超出了指定的等待時間。
//latch.await(long timeout, TimeUnit unit)
System.out.println("全部員工已經到達公司大門口,大巴車發動,前往活動目的地。");
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
//最後關閉線程池,但執行之前提交的任務,不接受新任務
threadPool.shutdown();
//關閉線程池,中止全部正在執行的活動任務,暫停處理正在等待的任務,並返回等待執行的任務列表。
//threadPool.shutdownNow();
}
}
}.net
//分佈式工做線程
class Employee implements Runnable{
private CountDownLatch latch;
private int employeeIndex;
public Employee(CountDownLatch latch,int employeeIndex){
this.latch = latch;
this.employeeIndex = employeeIndex;
}
@Override
public void run() {
try {
System.out.println("員工:"+employeeIndex+",正在前往公司大門口集合...");
Thread.sleep(10);
System.out.println("員工:"+employeeIndex+",已到達。");
} catch (Exception e) {
e.printStackTrace();
}finally{
//當前計算工做已結束,計數器減一
latch.countDown();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//執行coutDown()以後,繼續執行本身的工做,不受主線程的影響
System.out.println("員工:"+employeeIndex+",吃飯、喝水、拍照。");
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
打印輸出結果以下:
公司發送通知,每一位員工在週六早上8點到公司大門口集合
員工:1,正在前往公司大門口集合...
員工:1,已到達。
員工:2,正在前往公司大門口集合...
員工:2,已到達。
員工:1,吃飯、喝水、拍照。
員工:3,正在前往公司大門口集合...
員工:2,吃飯、喝水、拍照。
員工:3,已到達。
員工:4,正在前往公司大門口集合...
員工:3,吃飯、喝水、拍照。
員工:4,已到達。
員工:5,正在前往公司大門口集合...
員工:4,吃飯、喝水、拍照。
員工:5,已到達。
全部員工已經到達公司大門口,大巴車發動,前往活動目的地。
員工:5,吃飯、喝水、拍照。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
注意:
每個員工到達以後,執行countDown()方法,直到全部員工到達以後,計數器爲0,主線程纔會繼續執行。
但子線程執行了countDown()方法,以後會繼續本身的工做,好比上面的【吃飯、喝水、拍照】,是不受主線程是否阻塞、其它線程是否已經執行countDown()方法的影響的。
五、CountDownLatch與CyclicBarrier的對比能夠看: java多線程CyclicBarrier使用示例,讓線程起步走
六、參考: http://www.importnew.com/15731.html http://www.cnblogs.com/yezhenhan/archive/2012/01/07/2315652.html--------------------- 做者:逍遙不羈 來源:CSDN 原文:https://blog.csdn.net/javaloveiphone/article/details/54729821 版權聲明:本文爲博主原創文章,轉載請附上博文連接!