Java并發(fā)編程之CountDownLatch解讀
概念
- countDownLatch這個(gè)類使一個(gè)線程等待其他線程各自執(zhí)行完畢后再執(zhí)行。
- 是通過一個(gè)計(jì)數(shù)器來實(shí)現(xiàn)的,計(jì)數(shù)器的初始值是線程的數(shù)量。每當(dāng)一個(gè)線程執(zhí)行完畢后,計(jì)數(shù)器的值就-1,當(dāng)計(jì)數(shù)器的值為0時(shí),表示所有線程都執(zhí)行完畢,然后在閉鎖上等待的線程就可以恢復(fù)工作了。
源碼
countDownLatch類中只提供了一個(gè)構(gòu)造器:
//參數(shù)count為計(jì)數(shù)值
public CountDownLatch(int count) { }; 類中有三個(gè)方法是最重要的:
//調(diào)用await()方法的線程會(huì)被掛起,它會(huì)等待直到count值為0才繼續(xù)執(zhí)行
public void await() throws InterruptedException { };
//和await()類似,只不過等待一定的時(shí)間后count值還沒變?yōu)?的話就會(huì)繼續(xù)執(zhí)行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };
//將count值減1
public void countDown() { }; 自定義實(shí)現(xiàn)一個(gè)CountDownLatch
代碼如下:
public class KaneCountDownLatch {
private KaneCountDownLatch.Sync sync;
public KaneCountDownLatch(int count) {
this.sync = new KaneCountDownLatch.Sync(count);
}
public void countDown() {
this.sync.releaseShared(1);
}
public void await() {
this.sync.acquireShared(1);
}
class Sync extends AbstractQueuedSynchronizer {
public Sync(int count) {
this.setState(count);
}
protected int tryAcquireShared(int arg) {
return this.getState() == 0 ? 1 : -1;
}
protected boolean tryReleaseShared(int arg) {
int c;
int nextc;
do {
c = this.getState();
if (c == 0) {
return false;
}
nextc = c - 1;
} while(!this.compareAndSetState(c, nextc));
return nextc == 0;
}
}
}測(cè)試代碼如下:
public class CountDownLatch_Demo {
public static void main(String[] args) throws InterruptedException {
KaneCountDownLatch latch = new KaneCountDownLatch(6); //計(jì)數(shù)為6
for (int i = 0; i <6 ; i++) {
new Thread(()->{
System.out.println("開始準(zhǔn)備.....");
latch.countDown();//計(jì)數(shù)減一
}).start();
Thread.sleep(1000);
}
latch.await(); //每個(gè)線程執(zhí)行一次,則-1,在latch為0的時(shí)候開始向下運(yùn)行 這是這些線程都準(zhǔn)備就緒,然后去一起干同一件事
//還有一種方式, 將一個(gè)活分為多段,每個(gè)線程去干一段
// for (int i = 0; i <6 ; i++) {
// new Thread(()->{
// latch.countDown(); // 計(jì)數(shù)減一
// try {
// latch.await(); // 阻塞 -- > 0
// System.out.println("線程:"+Thread.currentThread().getName()+"執(zhí)行完畢");
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }).start();
// }
System.out.println("開始干活....");
}
}CountDownLatch和CyclicBarrier區(qū)別
- countDownLatch是一個(gè)計(jì)數(shù)器,線程完成一個(gè)記錄一個(gè),計(jì)數(shù)器遞減,只能只用一次
- CyclicBarrier的計(jì)數(shù)器更像一個(gè)閥門,需要所有線程都到達(dá),然后繼續(xù)執(zhí)行,計(jì)數(shù)器遞增,提供reset功能,可以多次使用
到此這篇關(guān)于Java并發(fā)編程之CountDownLatch解讀的文章就介紹到這了,更多相關(guān)CountDownLatch解讀內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java實(shí)現(xiàn)簡(jiǎn)單超市管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單超市管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-01-01
Spring項(xiàng)目如何實(shí)現(xiàn)帶請(qǐng)求鏈路id的日志記錄
我們?cè)谧鲰?xiàng)目的時(shí)候通常需要通過請(qǐng)求日志來排查定位線上問題,如果日志比較多而我們又需要查找整個(gè)請(qǐng)求的全部日志的時(shí)候會(huì)比較困難,下面我們就來看看如何用java aop實(shí)現(xiàn)請(qǐng)求id的日志記錄吧2024-12-12
Shiro整合Springboot和redis,jwt過程中的錯(cuò)誤shiroFilterChainDefinition問
這篇文章主要介紹了Shiro整合Springboot和redis,jwt過程中的錯(cuò)誤shiroFilterChainDefinition問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04
Java內(nèi)存之happens-before和重排序
在JMM(Java內(nèi)存模型)中,如果一個(gè)操作執(zhí)行的結(jié)果需要對(duì)另一個(gè)操作可見,那么這兩個(gè)操作之間必須存在happens-before關(guān)系。下面小編來簡(jiǎn)單介紹一下2019-05-05
Springboot?集成spring?cache緩存的解決方案
這篇文章主要介紹了Springboot?集成spring?cache緩存,使用緩存最關(guān)鍵的一點(diǎn)就是保證緩存與數(shù)據(jù)庫的數(shù)據(jù)一致性,本文給大家介紹最常用的緩存操作模式,對(duì)Springboot?集成spring?cache緩存操作流程感興趣的朋友一起看看吧2022-06-06
Hibernate一對(duì)多關(guān)聯(lián)雙向關(guān)聯(lián)代碼實(shí)現(xiàn)分享
Hibernate一對(duì)多關(guān)聯(lián)雙向關(guān)聯(lián)代碼實(shí)現(xiàn)分享,大家參考使用吧2013-12-12
MyBatis?如何使項(xiàng)目兼容多種數(shù)據(jù)庫的解決方案
要想做兼容多種數(shù)據(jù)庫,那毫無疑問,我們首先得明確我們要兼容哪些數(shù)據(jù)庫,他們的數(shù)據(jù)庫產(chǎn)品名稱是什么,本次我們講解了一套使項(xiàng)目兼容多種數(shù)據(jù)庫的方案,對(duì)MyBatis項(xiàng)目兼容多種數(shù)據(jù)庫操作方法感興趣的朋友一起看看吧2024-05-05

