1.背景:
- countDownLatch是在java1.5被引入,跟它一起被引入的工具類還有CyclicBarrier、Semaphore凑队、concurrentHashMap和BlockingQueue。
- 存在于java.util.cucurrent包下。
2.概念
- countDownLatch這個類使一個線程等待其他線程各自執(zhí)行完畢后再執(zhí)行垄提。
- 是通過一個計數(shù)器來實現(xiàn)的,計數(shù)器的初始值是線程的數(shù)量周拐。每當一個線程執(zhí)行完畢后怕磨,計數(shù)器的值就-1翅阵,當計數(shù)器的值為0時,表示所有線程都執(zhí)行完畢,然后在閉鎖上等待的線程就可以恢復工作了影所。
3.源碼
- countDownLatch類中只提供了一個構造器
//參數(shù)count為計數(shù)值
public CountDownLatch(int count) { };
- 類中有三個方法是最重要的:
//調用await()方法的線程會被掛起,它會等待直到count值為0才繼續(xù)執(zhí)行
public void await() throws InterruptedException { };
//和await()類似恍涂,只不過等待一定的時間后count值還沒變?yōu)?的話就會繼續(xù)執(zhí)行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };
//將count值減1
public void countDown() { };
4.示例
- 普通示例:
public class CountDownLatchTest {
public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(2);
System.out.println("主線程開始執(zhí)行…… ……");
//第一個子線程執(zhí)行
ExecutorService es1 = Executors.newSingleThreadExecutor();
es1.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
System.out.println("子線程:"+Thread.currentThread().getName()+"執(zhí)行");
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
}
});
es1.shutdown();
//第二個子線程執(zhí)行
ExecutorService es2 = Executors.newSingleThreadExecutor();
es2.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子線程:"+Thread.currentThread().getName()+"執(zhí)行");
latch.countDown();
}
});
es2.shutdown();
System.out.println("等待兩個線程執(zhí)行完畢…… ……");
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("兩個子線程都執(zhí)行完畢哑舒,繼續(xù)執(zhí)行主線程");
}
}
- 結果集:
主線程開始執(zhí)行…… ……
等待兩個線程執(zhí)行完畢…… ……
子線程:pool-1-thread-1執(zhí)行
子線程:pool-2-thread-1執(zhí)行
兩個子線程都執(zhí)行完畢,繼續(xù)執(zhí)行主線程
- 模擬并發(fā)示例:
public class Parallellimit {
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
CountDownLatch cdl = new CountDownLatch(100);
for (int i = 0; i < 100; i++) {
CountRunnable runnable = new CountRunnable(cdl);
pool.execute(runnable);
}
}
}
class CountRunnable implements Runnable {
private CountDownLatch countDownLatch;
public CountRunnable(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
try {
synchronized (countDownLatch) {
/*** 每次減少一個容量*/
countDownLatch.countDown();
System.out.println("thread counts = " + (countDownLatch.getCount()));
}
countDownLatch.await();
System.out.println("concurrency counts = " + (100 - countDownLatch.getCount()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
*CountDownLatch和CyclicBarrier區(qū)別:
1.countDownLatch是一個計數(shù)器播急,線程完成一個記錄一個脓钾,計數(shù)器遞減,只能只用一次
2.CyclicBarrier的計數(shù)器更像一個閥門桩警,需要所有線程都到達可训,然后繼續(xù)執(zhí)行,計數(shù)器遞增捶枢,提供reset功能握截,可以多次使用
原文鏈接
作者:指尖架構141319
鏈接:http://www.reibang.com/p/e233bb37d2e6