JUC之CountDownLatch
說完了CyclicBarier,現(xiàn)在來了解一下CountDownLatch的使用,還是先說說CountDownLatch的個人理解:就類似一個考場一樣,里面由考試的學(xué)生和監(jiān)考的老師(可以看作一個特殊的學(xué)生),考生做考卷的時間不一樣,那么交卷就會存在先后??纪暌粋€,那么這個考生就走出教室,完成任務(wù),教室里的學(xué)生就少了一個,直到最后一個考生離開,老師離開,那么這個教室就空閑了,就完成了任務(wù);這里的教室就是CounDownLatch,學(xué)生就是一個個的線程,學(xué)生之間互不影響,沒有說當(dāng)所有考生都考完才能一起離開;
- 構(gòu)造函數(shù)
// 只有一個構(gòu)造函數(shù),就是傳入計數(shù)的線程數(shù)量
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
- 常用方法
//這里還是列舉常用的方法,其中的Sync 是CountDownLatch中的一個內(nèi)部類,通過它來計數(shù);
// 調(diào)用這個讓之后的操作都等待CoundownLatch計數(shù)為0才執(zhí)行
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
// 將計數(shù)器較少一個
public void countDown() {
sync.releaseShared(1);
}
...
- 簡單使用
我們還是使用和CyclicBarrier中相同的例子,這里使用CountDownLatch來改造一下
public static void main(String[] args) throws InterruptedException {
Map<String, Integer> map = new ConcurrentHashMap<>();
CountDownLatch countDownLatch = new CountDownLatch(100);
for(int i = 0 ; i < 100; i++) {
new Thread(() -> {
try {
Integer test = map.merge("test", 1, Integer::sum);
countDownLatch.countDown();
// 這里不會等待
System.out.println("mission result: " + test);
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
// 執(zhí)行等待,直到所有線程完成;
countDownLatch.await();
// 等待完成之后執(zhí)行;
System.out.println(map.get("test"));
}
- 特點總結(jié)
CountDownLatch類似一個閥門,使用await將閥門關(guān)閉,進(jìn)行等待,計數(shù)器全部跑完之后開啟閥門,await之后的代碼繼續(xù)執(zhí)行;
和CyclicBarrier的不同是,它不會讓執(zhí)行了countDowm的線程進(jìn)行等待,類似執(zhí)行一個放走一個,而不是大家都等到最后一個完成一起走;
其次,CyclicBarrier可以使用reset重復(fù)利用,而CountDownLatch結(jié)束等待運行完成之后就失去效果了,也就是說他是一次性用品;
CountDownLatch會在計數(shù)器不為0的時候await一直等待,在一些springboot項目中,如果不是web項目,springboot啟動完成會自動關(guān)閉,所以會有使用CountDownLatch來維持springboot項目的啟動的手法。在看到springboot啟動類中的CountDownLatch不要覺得奇怪。