Java中的CountDownLatch同步工具類使用解析
CountDownLatch同步工具類
CountDownLatch初始化的時候必須指定一個count,await方法會一直阻塞直到調(diào)用countdown方法,count為0,當count為0時,所有的等待線程都會被釋放。
count是不能被重置的,如果想重復使用count,可以考慮CyclicBarrier。
CountDownLatch是一個同步工具類,用來協(xié)調(diào)多個線程之間的同步,或者是線程之間的通信。
CountDownLatch可以使主線程等待子線程完成自己的任務之后在繼續(xù)執(zhí)行,count為線程的數(shù)量,每當線程完成一個任務后,count減一,當count為0時,表示所有的任務都已經(jīng)完成,這時主線程就可以繼續(xù)執(zhí)行。
CountDownLatch的構(gòu)造函數(shù)
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}初始化的時候必須指定一個大于等于0的count,否則會拋出異常。
Sync(int count) {
setState(count);
}CountDownLatch的同步是使用了AQS的狀態(tài)代表count。
看一下它的countdown方法。
/**
* 如果count為0時,釋放所有的等待線程
* 如果當前的count比0大就要遞減
* 如果當前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設置state,如果state為0,說明所有的子線程都完成了操作,這是就要喚醒在同步隊列上的其他線程。
再來看一下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í)行任務");
}
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+"完成了任務");
c.countDown();
}
}執(zhí)行結(jié)果
子線程1完成了任務
子線程0完成了任務
子線程2完成了任務
主線程執(zhí)行任務
在多線程中,子線程需要完成各自的任務后,主線程才能利用子線程的結(jié)果進行整合,我們可以考慮CountDownLatch來控制并發(fā)。
CountDownLatch只是一個同步輔助類,當CountDownLatch的計數(shù)器未到0之前,所有調(diào)用await的方法都會阻塞,只有計數(shù)器為0,線程才能繼續(xù)往下執(zhí)行。CountDownLatch的計數(shù)器是不可重用的。
到此這篇關于Java中的CountDownLatch同步工具類使用解析的文章就介紹到這了,更多相關CountDownLatch同步工具類解析內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
被kafka-client和springkafka版本坑到自閉及解決
這篇文章主要介紹了被kafka-client和springkafka版本坑到自閉及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03

