1. 閉鎖
閉鎖是 J.U.C包下的一個同步組件。

閉鎖,圖從上往下看,countDown方法計(jì)數(shù)器減1
作用:
被等待線程調(diào)用countdown方法計(jì)數(shù)器減1,減到0時等待線程(調(diào)用await方法的線程)被喚醒。
- 閉鎖場景下,一個或者多個線程等待其他線程準(zhǔn)備好了才被喚醒。
一個閉鎖工作起來就像一道大門:直到閉鎖達(dá)到終點(diǎn)狀態(tài)之前,門一直是關(guān)閉的,沒有線程通過,在終點(diǎn)狀態(tài)到來的時候,門開了,允許所有線程都通過。一旦閉鎖到達(dá)了終點(diǎn)狀態(tài),他就不能夠在改變狀態(tài)了,所以它會永遠(yuǎn)保持敞開的狀態(tài)。
適用場景
1.確保一個計(jì)算不會執(zhí)行,直到它需要的資源被初始化。
2.確保一個服務(wù)不會開始,直到它依賴的服務(wù)都已經(jīng)開始。
3.等待直到活動的所有部分都為繼續(xù)處理做好準(zhǔn)備。比如王者榮耀需要等待所有玩家準(zhǔn)備才能開始。
代碼實(shí)例
public class CountDownLatchExample1 {
private final static int threadCount = 200;
public static void main(String[] args) throws Exception {
ExecutorService exec = Executors.newCachedThreadPool();
final CountDownLatch countDownLatch = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
final int threadNum = i;
exec.execute(() -> {
try {
test(threadNum);
} catch (Exception e) {
log.error("exception", e);
} finally {
countDownLatch.countDown();
}
});
}
countDownLatch.await();
log.info("finish");
exec.shutdown();
}
private static void test(int threadNum) throws Exception {
Thread.sleep(100);
log.info("{}", threadNum);
Thread.sleep(100);
}
}
2. 柵欄

圖從下往上看,await方法計(jì)數(shù)器加1
CyclicBarrier 字面意思是回環(huán)柵欄,回環(huán)的意思是它能夠被重復(fù)利用,當(dāng)然前提是在所有線程釋放了以后。
作用
柵欄描述的是線程間的相互等待,相互等待的線程都準(zhǔn)備好就可以繼續(xù)下去了。而且柵欄的計(jì)數(shù)器可以重置,這樣意味著其中有線程準(zhǔn)備過程執(zhí)行失敗可以全部重新準(zhǔn)備。
比較
| 能否復(fù)用 | 場景 | |
|---|---|---|
| CountDownLatch | 計(jì)數(shù)器不能重置 | 一個或者多個線程等待其他線程執(zhí)行完成 |
| CyclicBarrier | 計(jì)數(shù)器可以重置 | 一般用于一組線程互相等待至某個狀態(tài),然后這一組線程再同時執(zhí)行 |
代碼實(shí)例
public class CyclicBarrierExample1 {
private static CyclicBarrier barrier = new CyclicBarrier(5);
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newCachedThreadPool();
// 十個線程
for (int i = 0; i < 10; i++) {
final int threadNum = i;
Thread.sleep(1000);
executor.execute(() -> {
try {
race(Thread.currentThread().getName());
} catch (Exception e) {
System.out.println("exception "+ e);
}
});
}
executor.shutdown();
}
private static void race(String threadNum) throws Exception {
Thread.sleep(1000);
System.out.printf("%s is ready \n", threadNum);
barrier.await();
System.out.printf("%s continue \n", threadNum);
}
}
參考鏈接:
http://www.itdecent.cn/p/79f95bb81c67
http://www.itdecent.cn/p/5812bb54c44f