CountDownLatch
CountDownLatch是一個同步器, 允許一個或多個線程執(zhí)行完畢,再繼續(xù)執(zhí)行, 可以用來協(xié)調(diào)多個線程的同步。
CountDownLatch通過計數(shù)器實現(xiàn), 計數(shù)器的初始值是線程的數(shù)量, 每當一個線程執(zhí)行完畢, 計數(shù)器減1, 當計數(shù)器減為0或達到超時時間時, 等待的線程開始恢復執(zhí)行。
應用場景
某一個線程等待n個線程執(zhí)行完畢, CountDownLatch初始化為CountDownLatch(n), 當某個任務線程執(zhí)行執(zhí)行結束時,調(diào)用countDown方法,計數(shù)器減1, 當計數(shù)器減為0時, 表示n個任務線程全部執(zhí)行完畢,await的線程被喚醒, 開始執(zhí)行。典型場景為,主線程等待所有子任務結束,繼續(xù)下一步。 比如服務啟動時等待多個組件加載完畢,啟動服務。
多個線程等待某個線程執(zhí)行結束, 開始并發(fā)執(zhí)行, CountDownLatch初始化為CountDownLatch(1), 每個等待線程啟動時調(diào)用該CountDownLatch await方法被阻塞, 當主線程執(zhí)行完成, 計數(shù)器減1, 同時喚醒多個等待線程開始執(zhí)行。
重要方法
// 構造器
public CountDownLatch(int count) {}
//
public void await() throws InterruptedException {}
//
public boolean await(long timeout, TimeUnit unit) throws InterruptedException{}
//
public void countDown() {}
- 構造器
CountDownLatch的構造器僅有一個int參數(shù), 代表阻塞的線程數(shù)量。 - await
調(diào)用此方法的線程會被掛起, 直到count值降為0才會被喚醒。 - await(long timeout, TimeUnit unit)
調(diào)用此方法的線程會被掛起, 直到count值降為0或超時才會被喚醒。 - countDown
調(diào)用此方法, count值減1
示例
- 主線程等待n個線程執(zhí)行結束
final CountDownLatch countDownLatch = new CountDownLatch(10);
for(int i=0; i<10; i++){
final int finalI = i;
Runnable thread = new Runnable() {
@Override
public void run() {
System.out.println(finalI);
countDownLatch.countDown();
}
};
thread.run();
}
countDownLatch.await();
- 并發(fā)執(zhí)行
ExecutorService service = Executors.newCachedThreadPool();
final CountDownLatch countDownLatch = new CountDownLatch(1);
final CountDownLatch countDownLatch1 = new CountDownLatch(10);
final int[] a = {0};
for(int i=0; i<10; i++){
Runnable thread = new Runnable() {
@Override
public void run() {
try {
System.out.println(a[0]);
countDownLatch.await();
a[0] += 1;
countDownLatch1.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
service.execute(thread);
}
countDownLatch.countDown();
countDownLatch1.await();
System.out.println(a[0]);
原理解析
TODO AQS