Java中的CountDownLatch同步工具類使用解析
CountDownLatch同步工具類
CountDownLatch初始化的時(shí)候必須指定一個(gè)count,await方法會(huì)一直阻塞直到調(diào)用countdown方法,count為0,當(dāng)count為0時(shí),所有的等待線程都會(huì)被釋放。
count是不能被重置的,如果想重復(fù)使用count,可以考慮CyclicBarrier。
CountDownLatch是一個(gè)同步工具類,用來協(xié)調(diào)多個(gè)線程之間的同步,或者是線程之間的通信。
CountDownLatch可以使主線程等待子線程完成自己的任務(wù)之后在繼續(xù)執(zhí)行,count為線程的數(shù)量,每當(dāng)線程完成一個(gè)任務(wù)后,count減一,當(dāng)count為0時(shí),表示所有的任務(wù)都已經(jīng)完成,這時(shí)主線程就可以繼續(xù)執(zhí)行。
CountDownLatch的構(gòu)造函數(shù)
public CountDownLatch(int count) { if (count < 0) throw new IllegalArgumentException("count < 0"); this.sync = new Sync(count); }
初始化的時(shí)候必須指定一個(gè)大于等于0的count,否則會(huì)拋出異常。
Sync(int count) { setState(count); }
CountDownLatch的同步是使用了AQS的狀態(tài)代表count。
看一下它的countdown方法。
/** * 如果count為0時(shí),釋放所有的等待線程 * 如果當(dāng)前的count比0大就要遞減 * 如果當(dāng)前count為0什么也不做 */ public void countDown() { sync.releaseShared(1); }
本質(zhì)還是調(diào)用了AQS的releaseShared方法。
public final boolean releaseShared(int arg) { if (tryReleaseShared(arg)) { doReleaseShared(); return true; } return false; }
protected boolean tryReleaseShared(int releases) { // Decrement count; signal when transition to zero for (;;) { int c = getState(); if (c == 0) return false; int nextc = c-1; if (compareAndSetState(c, nextc)) return nextc == 0; } }
countdown就是釋放鎖的操作,每被調(diào)用一次,state就減一。首先嘗試釋放鎖,利用CAS設(shè)置state,如果state為0,說明所有的子線程都完成了操作,這是就要喚醒在同步隊(duì)列上的其他線程。
再來看一下await方法。
public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); }
public final void acquireSharedInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (tryAcquireShared(arg) < 0) doAcquireSharedInterruptibly(arg); }
protected int tryAcquireShared(int acquires) { return (getState() == 0) ? 1 : -1; }
嘗試獲取鎖,如果state為0,表示獲取鎖成功,如果state不為0,表示獲取鎖失敗,調(diào)用doAcquireSharedInterruptibly方法阻塞直到成功獲取到鎖。
CountDownLatch的使用
public static void main(String[] args) throws Exception { java.util.concurrent.CountDownLatch c = new java.util.concurrent.CountDownLatch(3); ExecutorService es = Executors.newCachedThreadPool(); for (int i = 0; i < 3; i++) { es.execute(new Task(i, c)); } c.await(); System.out.println("主線程執(zhí)行任務(wù)"); } public static class Task implements Runnable { private int m; private java.util.concurrent.CountDownLatch c; public Task(int m,java.util.concurrent.CountDownLatch c) { this.m = m; this.c = c; } @Override public void run() { System.out.println("子線程"+m+"完成了任務(wù)"); c.countDown(); } }
執(zhí)行結(jié)果
子線程1完成了任務(wù)
子線程0完成了任務(wù)
子線程2完成了任務(wù)
主線程執(zhí)行任務(wù)
在多線程中,子線程需要完成各自的任務(wù)后,主線程才能利用子線程的結(jié)果進(jìn)行整合,我們可以考慮CountDownLatch來控制并發(fā)。
CountDownLatch只是一個(gè)同步輔助類,當(dāng)CountDownLatch的計(jì)數(shù)器未到0之前,所有調(diào)用await的方法都會(huì)阻塞,只有計(jì)數(shù)器為0,線程才能繼續(xù)往下執(zhí)行。CountDownLatch的計(jì)數(shù)器是不可重用的。
到此這篇關(guān)于Java中的CountDownLatch同步工具類使用解析的文章就介紹到這了,更多相關(guān)CountDownLatch同步工具類解析內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Java分布式系統(tǒng)中session一致性問題
這篇文章主要介紹了Java分布式系統(tǒng)中session一致性問題,對分布式系統(tǒng)感興趣的同學(xué),要仔細(xì)看一下2021-04-04Springboot實(shí)現(xiàn)導(dǎo)入導(dǎo)出Excel的方法
今天帶各位小伙伴學(xué)習(xí)Springboot實(shí)現(xiàn)導(dǎo)入導(dǎo)出Excel的方法,文中有非常詳細(xì)的介紹,對正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下2021-05-05深入了解Spring中最常用的11個(gè)擴(kuò)展點(diǎn)
我們一說到spring,可能第一個(gè)想到的是?IOC(控制反轉(zhuǎn))?和?AOP(面向切面編程)。除此之外,我們在使用spring的過程中,有沒有發(fā)現(xiàn)它的擴(kuò)展能力非常強(qiáng)。今天就來跟大家一起聊聊,在Spring中最常用的11個(gè)擴(kuò)展點(diǎn)2022-09-09Java編寫程序之輸入一個(gè)數(shù)字實(shí)現(xiàn)該數(shù)字階乘的計(jì)算
這篇文章主要介紹了Java編寫程序之輸入一個(gè)數(shù)字實(shí)現(xiàn)該數(shù)字階乘的計(jì)算,本文通過實(shí)例代碼給大家介紹的非常想詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02SpringBoot項(xiàng)目實(shí)現(xiàn)日志打印SQL的常用方法(包括SQL語句和參數(shù))
有時(shí)候遇到問題需要根據(jù)我們編寫的SQL進(jìn)行分析,但如果不進(jìn)行一些開發(fā)或者配置的話,這些SQL是不會(huì)打印到控制臺(tái)的,它們默認(rèn)是隱藏的。下面給大家介紹幾種常用的方法,感興趣的朋友跟隨小編一起看看吧2024-04-04java正則表達(dá)式對特殊字符的轉(zhuǎn)義以及異?,F(xiàn)象
這篇文章主要給大家介紹了關(guān)于java正則表達(dá)式對特殊字符的轉(zhuǎn)義以及異?,F(xiàn)象的相關(guān)資料,在Java中使用正則表達(dá)式匹配特殊字符也需要使用轉(zhuǎn)義字符"\",需要的朋友可以參考下2023-06-06