使用counDownLatch

1.CountDownLatch和CyclicBarrier的相似處和不同處:

CountDownLatch是通過(guò)一個(gè)計(jì)數(shù)器來(lái)實(shí)現(xiàn)的,當(dāng)我們?cè)趎ew 一個(gè)CountDownLatch對(duì)象的時(shí)候需要帶入該計(jì)數(shù)器值,該值就表示了線程的數(shù)量。每當(dāng)一個(gè)線程完成自己的任務(wù)后,計(jì)數(shù)器的值就會(huì)減1。當(dāng)計(jì)數(shù)器的值變?yōu)?時(shí),就表示所有的線程均已經(jīng)完成了任務(wù),然后就可以恢復(fù)等待的線程繼續(xù)執(zhí)行了。

雖然,CountDownlatch與CyclicBarrier有那么點(diǎn)相似,但是他們還是存在一些區(qū)別的:

CountDownLatch的作用是允許1或N個(gè)線程等待其他線程完成執(zhí)行;而CyclicBarrier則是允許N個(gè)線程相互等待

CountDownLatch的計(jì)數(shù)器無(wú)法被重置;CyclicBarrier的計(jì)數(shù)器可以被重置后使用,因此它被稱為是循環(huán)的barrier。


CountDownLatch最關(guān)鍵的一個(gè)參數(shù)就是count。

CountDownLatch的幾個(gè)核心方法:

? await()方法 //countDownLatch的await()方法會(huì)使當(dāng)前線程在鎖存器倒計(jì)數(shù)至零之前,一直等待,除非線程被中斷。

? countDown()方法? // countDown()方法可以遞減鎖存器的計(jì)數(shù),如果計(jì)數(shù)到達(dá)零,則釋放所有等待的線程。

總結(jié)起來(lái),就是CountDownLatch有三個(gè)核心部分:

? ? ? ? ? ? p1.是 count? 計(jì)數(shù)器

? ? p2.是 await()方法,使當(dāng)前線程阻塞,直到count的值為0。

? ? p3.是 countDown()方法,使計(jì)數(shù)器器的值減一。

應(yīng)用場(chǎng)景是這樣的:

線程A的運(yùn)行需要同時(shí)擁有N個(gè)資源,而這N個(gè)資源卻被n1,n2,n3, ......,nn個(gè)線程分別占有者。

所以:A要想運(yùn)行的話,它就必須等待n1,n2,n3,......,nn這n個(gè)線程都把各自占有的資源釋放了才行。

其實(shí),它就是一把 共享資源鎖。


2.用一段故事說(shuō)明一下

相當(dāng)于現(xiàn)在有一個(gè)保險(xiǎn)柜,這個(gè)保險(xiǎn)柜上有三把鎖,只有把這三把鎖都打開才能打開保險(xiǎn)柜 。而這三把鎖卻被分別交給了三個(gè)管理員A,B,C手中。所以,如果我們想打開這個(gè)保險(xiǎn)柜的話,就必須集齊所有的三把鎖。

有一天老板來(lái)視察工作,想看下保險(xiǎn)柜的錢少了,沒有,就找來(lái)經(jīng)理。讓經(jīng)理開門,經(jīng)理說(shuō),你等一下,我打三個(gè)電話,把人叫齊了才能把門打開。你現(xiàn)在必須先等一下。于是,經(jīng)理叫開始逐個(gè)打電話,他先打給A,"趕快帶上鑰匙來(lái)公司一趟,老板在等著你",1分鐘后,A來(lái)了,帶來(lái)了一把鑰匙。然后,經(jīng)理繼續(xù)給B打電話,"兄弟,趕快來(lái)公司一趟,把鑰匙帶上,老板要檢查保險(xiǎn)柜"。2分鐘后,B來(lái)了。最后,經(jīng)理又給C打了一個(gè)電話,"你他娘的,帶上鑰匙趕快來(lái)公司。" 5分鐘后,C也來(lái)了,就這樣。老板在等候了8分鐘后終于集齊了三把鑰匙,打開了保險(xiǎn)柜,看到了自己的小金庫(kù)。經(jīng)過(guò)漫長(zhǎng)而艱辛的等待他欣慰地漏出了笑容。



3.demo案例

需求:

過(guò)來(lái)一個(gè)請(qǐng)求,這個(gè)請(qǐng)求傳遞過(guò)來(lái)一個(gè)集合,要求我們分別算出該集合元素的總和、積、所有偶數(shù)值,并存入庫(kù)中,然后把處理結(jié)果返回客戶端。


3.1 創(chuàng)建三個(gè)負(fù)責(zé)和、積、偶數(shù)值的Runnable

public class AddRunnable implements Runnable {

private? CountDownLatch? countDown;

private? List<Integer>? dataList;

public AddRunnable(CountDownLatch countDown,List<Integer> dataList) {

super();

this.countDown = countDown;

this.dataList = dataList;

}

@Override

public void run() {

Thread.currentThread().setName("sum線程");

//計(jì)算和

Long sum=0l;

for (Integer value : dataList) {

sum=sum+value;

}

//計(jì)算出來(lái)總和后,把結(jié)果存庫(kù)

System.out.println("計(jì)算結(jié)果是:"+sum+"? 把計(jì)算結(jié)果存庫(kù)!");

countDown.countDown();//釋放鎖

System.out.println(Thread.currentThread().getName()+"釋放了一把共享鎖");

}

}



乘積:

public class MultiRunnable implements Runnable {

private? CountDownLatch? countDown;

private? List<Integer>? dataList;

public MultiRunnable(CountDownLatch countDown, List<Integer> dataList) {

super();

this.countDown = countDown;

this.dataList = dataList;

}

@Override

public void run() {

// TODO Auto-generated method stub

Thread.currentThread().setName("muti線程");

//計(jì)算和

Long muti=1l;

for (Integer value : dataList) {

muti=muti*value;

System.out.println(muti);

}

//計(jì)算出來(lái)總和后,把結(jié)果存庫(kù)

System.out.println("乘積結(jié)果是:"+muti+"? 把乘積結(jié)果存庫(kù)!");

countDown.countDown();//釋放鎖

System.out.println(Thread.currentThread().getName()+"釋放了一把共享鎖");

}

}


所有偶數(shù)值:

public class OddRunnable implements Runnable {

? ? private? CountDownLatch? countDown;

private? List<Integer>? dataList;

public OddRunnable(CountDownLatch countDown, List<Integer> dataList) {

super();

this.countDown = countDown;

this.dataList = dataList;

}

@Override

public void run() {

// TODO Auto-generated method stub

// TODO Auto-generated method stub

Thread.currentThread().setName("odd線程");

List<Integer> oddList=new ArrayList<Integer>();

// 計(jì)算和

for (Integer value : dataList) {

if(value%2==0) {

oddList.add(value);

}

}

// 計(jì)算出來(lái)總和后,把結(jié)果存庫(kù)

System.out.println("求偶結(jié)果是:" + oddList.size() + "? 把求偶結(jié)果存庫(kù)!");

countDown.countDown();// 釋放鎖

System.out.println(Thread.currentThread().getName() + "釋放了一把共享鎖");

}

}




測(cè)試:

/**

* 需求:

*? ? 過(guò)來(lái)一個(gè)請(qǐng)求,這個(gè)請(qǐng)求傳遞過(guò)來(lái)一個(gè)集合,要求我們分別算出該集合元素的總和、積、所有偶數(shù)值,并存入庫(kù)中,然后把處理結(jié)果返回客戶端。

* @author chihaojie

*

*/

public class CountDownLatchTest {

private static? CountDownLatch? countDown;

public static void main(String[] args) {

//只有在其他三個(gè)子運(yùn)算全部完成時(shí),當(dāng)前線程才能繼續(xù)

//ExecutorService executorService = Executors.newFixedThreadPool(3);

List<Integer>? dataList=new ArrayList<Integer>();

? ? ? ? for (int i = 0; i < 10; i++) {

? ? ? ? dataList.add(i+1);

}

? ? ? ? System.out.println(dataList);

? ? ? //處理

? ? ? ? countDown=new CountDownLatch(3);

? ? ? ? //開啟三個(gè)線程

? ? ? ? new Thread(new AddRunnable(countDown,? dataList)).start();;

? ? ? ? new Thread(new MultiRunnable(countDown, dataList)).start();;

? ? ? ? new Thread(new OddRunnable(countDown, dataList)).start();;

? ? ? ? //執(zhí)行

? ? ? ? try {

countDown.await();

System.out.println("所有的線程都運(yùn)算完了");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}




運(yùn)行結(jié)果
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容