Java并發(fā)編程之CountDownLatch原理詳解
一、CountDownLatch介紹
在日常開(kāi)發(fā)中經(jīng)常會(huì)遇到需要在主線程中開(kāi)啟多個(gè)線程去并行執(zhí)行任務(wù),并且主線程需要等待所有子線程執(zhí)行完畢后再進(jìn)行匯總的場(chǎng)景。
在 CountDownLatch 出現(xiàn)之前一般都使用線程的join()方法來(lái)實(shí)現(xiàn)這一點(diǎn),但是 join 方法不夠靈活,不能夠滿足不同場(chǎng)景的需要,所以JDK開(kāi)發(fā)組提供了 CountDownLatch 這個(gè)類,使用CountDownLatch 會(huì)更優(yōu)雅。
并且CountDownLatch 可以在子線程的任何位置讓 await 方法返回而不一定必須線程結(jié)束,這比join更加靈活。使用 CountDownLatch 的代碼如下:
public static void main(String[] args) throws InterruptedException {
//內(nèi)部sync同步器的state值設(shè)為3
CountDownLatch countDownLatch = new CountDownLatch(3);
for (int i = 1;i <= 3;i++) {
new Thread(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("目標(biāo)代碼塊運(yùn)行完畢");
//每調(diào)用一次countDown()內(nèi)部調(diào)用releaseShared(1)都會(huì)使state值減一
countDownLatch.countDown();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("線程結(jié)束");
}).start();
}
System.out.println("所有線程已啟動(dòng)");
//主線程調(diào)用await()方法后就會(huì)進(jìn)入阻塞,直到所有線程調(diào)用了countDown()使state值被減為0,或者主線程被中斷,才會(huì)從阻塞返回
countDownLatch.await();
System.out.println("所有線程目標(biāo)代碼塊已運(yùn)行完畢");
}
二、CountDownLatch原理
CountDownLatch類中使用了一個(gè)繼承自AQS的共享鎖Sync對(duì)象,構(gòu)造CountDownLatch對(duì)象時(shí)會(huì)將傳入的線程數(shù)值設(shè)為AQS的state值
當(dāng)一個(gè)線程結(jié)束運(yùn)行調(diào)用countDown()方法時(shí),內(nèi)部調(diào)用releaseShared(1)時(shí)調(diào)用Sync中重寫(xiě)的鉤子方法tryReleaseShared()都會(huì)使state值減一,當(dāng)被state被減為0后tryReleaseShared才會(huì)返回true,繼而調(diào)用doReleaseShared喚醒同步隊(duì)列中被阻塞的線程



主線程調(diào)用await()方法后就會(huì)進(jìn)入阻塞,其內(nèi)部調(diào)用的acquireSharedInterruptibly方法,只有當(dāng)鉤子方法tryAcquireShared返回值>=0時(shí)才能拿到鎖,而Sync中重寫(xiě)的tryAcquireShared只有當(dāng)state為0才會(huì)返回1,否則返回-1,因此只有到最后一個(gè)線程調(diào)用了countDown()使state值被減為0繼而喚醒同步隊(duì)列中阻塞的主線程,或者主線程被中斷,才會(huì)從阻塞返回。
到此這篇關(guān)于Java并發(fā)編程之CountDownLatch原理詳解的文章就介紹到這了,更多相關(guān)CountDownLatch原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java實(shí)現(xiàn)從網(wǎng)上下載圖片到本地的方法
這篇文章主要介紹了java實(shí)現(xiàn)從網(wǎng)上下載圖片到本地的方法,涉及java針對(duì)文件操作的相關(guān)技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-07-07
HashMap實(shí)現(xiàn)保存兩個(gè)key相同的數(shù)據(jù)
這篇文章主要介紹了HashMap實(shí)現(xiàn)保存兩個(gè)key相同的數(shù)據(jù)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
Spring?Boot實(shí)現(xiàn)分布式系統(tǒng)中的服務(wù)發(fā)現(xiàn)和注冊(cè)(最新推薦)
在本文中,我們深入探討了Spring?Boot如何實(shí)現(xiàn)分布式系統(tǒng)中的服務(wù)發(fā)現(xiàn)和注冊(cè),我們使用Eureka作為服務(wù)注冊(cè)中心,Ribbon作為負(fù)載均衡器,Hystrix作為熔斷器,成功地實(shí)現(xiàn)了服務(wù)發(fā)現(xiàn)、服務(wù)注冊(cè)、負(fù)載均衡和服務(wù)熔斷等功能,需要的朋友參考下吧2023-06-06
Java中List轉(zhuǎn)Map List實(shí)現(xiàn)的幾種姿勢(shì)
本文主要介紹了Java中List轉(zhuǎn)Map List實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06
java 交換兩個(gè)數(shù)據(jù)的方法實(shí)例詳解
這篇文章主要介紹了java 交換兩個(gè)數(shù)據(jù)的方法實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2016-12-12
Java實(shí)現(xiàn)郵箱發(fā)送功能實(shí)例(阿里云郵箱推送)
這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)郵箱發(fā)送功能的相關(guān)資料,利用阿里云郵箱推送,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09

