Java中CountDownLatch進(jìn)行多線程同步詳解及實(shí)例代碼
Java中CountDownLatch進(jìn)行多線程同步詳解
CountDownLatch介紹
在前面的Java學(xué)習(xí)筆記中,總結(jié)了Java中進(jìn)行多線程同步的幾個(gè)方法:
1、synchronized關(guān)鍵字進(jìn)行同步。
2、Lock鎖接口及其實(shí)現(xiàn)類(lèi)ReentrantLock、ReadWriteLock鎖實(shí)現(xiàn)同步。
3、信號(hào)量Semaphore實(shí)現(xiàn)同步。
其中,synchronized關(guān)鍵字和Lock鎖解決的是多個(gè)線程對(duì)同一資源的并發(fā)訪問(wèn)問(wèn)題。信號(hào)量Semaphore解決的是多副本資源的共享訪問(wèn)問(wèn)題。
今天,來(lái)學(xué)習(xí)一下Java中的另外一個(gè)多線程同步輔助類(lèi):CountDownLatch。官方文檔對(duì)CountDownLatch的解釋是:在完成一組正在其他線程中執(zhí)行的操作之前,它允許一個(gè)或多個(gè)線程一直等待。也就是說(shuō),CountDownLatch控制某個(gè)或者多個(gè)線程,讓它們等待多個(gè)線程完成某項(xiàng)任務(wù)后,再啟動(dòng)。CountDownLatch主要是用來(lái)同步多個(gè)任務(wù)的執(zhí)行,區(qū)別于其他的synchronized關(guān)鍵字,鎖,信號(hào)量是用來(lái)同步共享資源的。
CountDownLatch實(shí)現(xiàn)原理簡(jiǎn)介:
CountDownLatch內(nèi)部維護(hù)一個(gè)計(jì)數(shù)器,計(jì)數(shù)器的值為待完成的任務(wù)數(shù)N,需要等待這N個(gè)任務(wù)完成的線程調(diào)用
CountDownLatch的await()方法使自己進(jìn)入休眠等待狀態(tài)。
當(dāng)某一個(gè)任務(wù)線程完成某一個(gè)任務(wù)后調(diào)用CountDownLatch的countDown()方法來(lái)表示自己的任務(wù)已完成,此時(shí)CountDownLatch的計(jì)數(shù)器值減1,當(dāng)所有的任務(wù)完成式,計(jì)數(shù)器的值為0。當(dāng)計(jì)數(shù)器值為0時(shí),CountDownLatch將喚醒所有因await()方法進(jìn)入休眠的線程。
CountDownLatch的使用:
CountDownLatch的使用主要有3點(diǎn):
1、CountDownLatch的聲明及初始化,在初始化時(shí)需要指定等待完成的任務(wù)數(shù)。
2、某一個(gè)任務(wù)完成時(shí)調(diào)用CountDownLatch的countDown()方法,向CountDownLatch報(bào)告自己的任務(wù)已經(jīng)完成,
3、需要等待任務(wù)完成的線程調(diào)用CountDownLatch的await()方法,調(diào)用后該線程將進(jìn)入休眠,并在所有任務(wù)數(shù)完成后CountDownLatch的計(jì)數(shù)器值為0時(shí),因await()方法進(jìn)行休眠的線程將被喚醒。
在此本人在Java 7并發(fā)編程實(shí)戰(zhàn)手冊(cè)該書(shū)中的CountDownLatch使用示例的基礎(chǔ)上做了部分改進(jìn),來(lái)演示CountDownLatch的使用詳情:
模擬10個(gè)參會(huì)者和一個(gè)主持人參加的一個(gè)會(huì)以,每個(gè)參會(huì)者及主持人需要等待其他的參會(huì)者均到場(chǎng)簽到之后,才能開(kāi)始會(huì)以并發(fā)言。為此,先創(chuàng)建一個(gè)會(huì)以管理的類(lèi)VideoConference,其提供一個(gè)arrive()方法供參會(huì)者調(diào)用來(lái)進(jìn)行簽到。會(huì)議管理的擁有者是主持人,其等待每個(gè)參會(huì)者的簽到:
public class VideoConference implements Runnable{
private final CountDownLatch countDownLatch;
private int number;
public VideoConference(int number) {
this.number = number;
this.countDownLatch = new CountDownLatch(number);//使用Number初始化其內(nèi)部的計(jì)數(shù)器,當(dāng)初始化完成后,不能再次初始化
}
public void arrive(String name){
//每個(gè)需要同步的任務(wù),在任務(wù)完成時(shí),需要調(diào)用該方法
countDownLatch.countDown();//countDownLatch內(nèi)部的計(jì)數(shù)器減1
System.out.print("arrive:"+name+"\n");
try{
countDownLatch.await();//await方法是線程進(jìn)入休眠,當(dāng)countDownLatch計(jì)數(shù)器為0時(shí),將被喚醒
//線程被喚醒,在這里可以執(zhí)行一系列任務(wù)
System.out.print("name:"+name + " say:let's start..." +"\n");
}catch (InterruptedException e){
e.printStackTrace();
}
}
public void run(){
System.out.print("has arrive:"+(number-countDownLatch.getCount())+"\n");
try{
countDownLatch.await();//await方法是線程進(jìn)入休眠,當(dāng)countDownLatch計(jì)數(shù)器為0時(shí),將被喚醒
//線程被喚醒,在這里可以執(zhí)行一系列任務(wù)
System.out.print("all arrived:"+(number-countDownLatch.getCount())+"\n");
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
創(chuàng)建一個(gè)參會(huì)者類(lèi)Participant:
public class Participant implements Runnable{
private VideoConference videoConference;
private String name;
public Participant(String name, VideoConference videoConference) {
this.name = name;
this.videoConference = videoConference;
}
public void run(){
try {
//do something
Thread.sleep(50);
//
videoConference.arrive(name);
}catch (InterruptedException e){
e.printStackTrace();
}
}
public static void main(String[] args){
VideoConference videoConference = new VideoConference(10);
Thread videoThread = new Thread(videoConference);
videoThread.start();
for(int i=0; i<10; i++){
Thread thread = new Thread(new Participant("participant:"+i,videoConference));
thread.start();
}
}
}
Participant類(lèi)中的main函數(shù)首先創(chuàng)建了一個(gè)需要10個(gè)參會(huì)者參加的一個(gè)會(huì)議,之后,創(chuàng)建了10個(gè)參會(huì)者并逐個(gè)簽到,在10個(gè)參會(huì)者都簽到之后,每個(gè)參會(huì)者及主持人將被"喚醒"并發(fā)言。
總結(jié):
CountDownLatch類(lèi)解決的是多線程間的同步等待、任務(wù)協(xié)調(diào)問(wèn)題,應(yīng)用在如在啟動(dòng)某個(gè)程序的主功能前,需要前置完成配置環(huán)境檢查、網(wǎng)絡(luò)檢查等多個(gè)子任務(wù)等類(lèi)似的場(chǎng)景。在Java中,除了使用CountDownLatch來(lái)實(shí)現(xiàn)多線程間的同步等待以外,還可以使用柵欄技術(shù)CyclicBarrier來(lái)實(shí)現(xiàn)多線程間的同步等待、任務(wù)協(xié)調(diào)。
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
- java多線程CountDownLatch與線程池ThreadPoolExecutor/ExecutorService案例
- Java countDownLatch如何實(shí)現(xiàn)多線程任務(wù)阻塞等待
- 如何使用CountDownLatch同步j(luò)ava多線程
- java使用CountDownLatch等待多線程全部執(zhí)行完成
- JAVA多線程CountDownLatch使用詳解
- Java中多線程同步類(lèi) CountDownLatch
- 詳解Java多線程編程中CountDownLatch阻塞線程的方法
- Java多線程編程之CountDownLatch同步工具使用實(shí)例
- Java多線程之同步工具類(lèi)CountDownLatch
相關(guān)文章
解決java字符串轉(zhuǎn)換成時(shí)間Unparseable date出錯(cuò)的問(wèn)題
這篇文章主要介紹了解決java字符串轉(zhuǎn)換成時(shí)間Unparseable date出錯(cuò)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
鴻蒙HarmonyOS App開(kāi)發(fā)造輪子之自定義圓形圖片組件的實(shí)例代碼
這篇文章主要介紹了鴻蒙HarmonyOS App開(kāi)發(fā)造輪子之自定義圓形圖片組件,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01
IntelliJ IDEA安裝插件阿里巴巴Java開(kāi)發(fā)手冊(cè)(Alibaba Java Coding Guidelines
這篇文章主要介紹了IntelliJ IDEA安裝插件阿里巴巴Java開(kāi)發(fā)手冊(cè)(Alibaba Java Coding Guidelines),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05
springboot+redis 實(shí)現(xiàn)分布式限流令牌桶的示例代碼
這篇文章主要介紹了springboot+redis 實(shí)現(xiàn)分布式限流令牌桶 ,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
springCloud gateWay 統(tǒng)一鑒權(quán)的實(shí)現(xiàn)代碼
這篇文章主要介紹了springCloud gateWay 統(tǒng)一鑒權(quán)的實(shí)現(xiàn)代碼,統(tǒng)一鑒權(quán)包括鑒權(quán)邏輯和代碼實(shí)現(xiàn),本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-02-02
Java日期時(shí)間格式化操作DateUtils 的整理
這篇文章主要介紹了Java日期時(shí)間格式化操作DateUtils 的整理的相關(guān)資料,這里總結(jié)了java日期格式化的操作,需要的朋友可以參考下2017-07-07
淺談為什么重寫(xiě)equals()就要重寫(xiě)hashCode()
困擾我很久的問(wèn)題,一直不明白為什么重寫(xiě)equals()方法的時(shí)候要重寫(xiě)hashCode()方法,這次總算弄明白了,作此分享,感興趣的可以了解一下2021-10-10

