countdowntlatch的作用是讓主線程等待所有的子執行緒執行完畢之後再進行執行,同時它是基於aqs進行實現的,所以它底層肯定是通過自定義aqs共享模式下的同步器來實現的,該同步器需要重寫aqs提供的tryacquireshared()以及tryreleaseshared()方法,只需要告訴aqs是否嘗試獲取同步資源以及釋放同步資源成功即可。
aqs子類需要定義以及維護同步狀態的值,在countdownlatch中,同步狀態state的值為同步資源的個數。
// 存在乙個全域性的同步器屬性
private final sync sync;
/*** 構建方法初始化同步器,並指定同步資源的個數
*/public countdownlatch(int count)
/*** 讓主線程進行阻塞
*/public void await() throws interruptedexception
public boolean await(long timeout, timeunit unit)
throws interruptedexception
/*** 讓倒數器-1
*/public void countdown()
public long getcount()
public string tostring()
}可以看到countdownlatch中定義了乙個同步器,然後存在乙個全域性的同步器屬性,並且通過構建方法來初始化同步器,通過count引數來指定同步資源的個數。
同時countdownlatch的await()方法將會直接呼叫aqs的acquiresharedinterruptibly()方法,countdown()方法直接呼叫aqs的releaseshared()方法。
private static final class sync extends abstractqueuedsynchronizer
/*** 獲取可用的同步資源個數(就是倒數器當前的值)
*/int getcount()
/*** 嘗試獲取同步資源
*/protected int tryacquireshared(int acquires)
/*** 嘗試釋放同步資源
*/protected boolean tryreleaseshared(int releases) }}
tryacquireshared()方法用於嘗試獲取同步資源,同時aqs規定,如果獲取同步資源成功則返回剩餘的可用資源個數,否則返回負數,但在countdownlatch的同步器的tryacquireshared()方法中,只有當同步狀態的值為0時,才表示獲取同步資源成功,方法返回1,否則都為獲取同步資源失敗,方法返回-1。
tryreleaseshared()方法用於嘗試釋放同步資源,同時aqs規定,如果釋放同步資源成功,則返回true,否則返回false,一般情況下方法都會返回true(當前同步資源的值 + 要釋放的同步資源個數),但是在countdownlatch的同步器的tryreleaseshared()方法中,並沒有累加同步狀態的值,而是當執行緒每次釋放同時資源時,都會將同步狀態的值-1,只有當執行緒釋放同步資源後,同步狀態的值為0時,該方法才會返回true。
1.首先建立乙個countdownlatch例項,並指定倒數器的閾值。
2.主線程呼叫countdownlatch的await()方法進行阻塞,該方法會直接呼叫aqs的acquiresharedinterruptibly()方法,acquiresharedinterruptibly()方法又會呼叫同步器的tryacquireshared()方法,嘗試獲取同步資源,tryacquireshared()方法只有當同步狀態的值為0時,才表示獲取同步資源成功,方法返回1,由於目前同步狀態的值不為0,因此方法返回-1,因此該執行緒將會封裝成node節點,然後加入到等待佇列當中,該執行緒將會進行阻塞。
3.子執行緒呼叫countdownlatch的countdown()方法讓倒數器-1,該方法會直接呼叫aqs的releaseshared()方法,releaseshared()方法又會呼叫同步器的tryreleaseshared()方法,嘗試釋放同步資源,但是在tryreleaseshared()方法中,每次當執行緒釋放同步資源時,都會將同步狀態的值-1,只有當執行緒釋放同步資源後,同步狀態的值為0時,該方法才會返回true,否則返回false,如果tryreleaseshared()方法返回false,那麼就不做任何處理,只有當該方法返回true時,也就是最後乙個子執行緒執行了countdown()方法,將同步狀態的值設定為0,那麼就會喚醒離頭節點最近的同時等待狀態不為cancelled的後繼節點,也就是主線程,然後主線程呼叫tryacquireshared()方法嘗試獲取同步資源,由於當前同步狀態的值已經為0,因此tryacquireshared()方法返回1,然後主線程直接返回,做自己的事情。
countdownlatch為什麼不能重用?
不能重用,因此當主線程被喚醒後,然後呼叫tryacquireshared()方法獲取了同步資源,然後就直接返回,做自己的事情,永遠都不會釋放同步資源,因此不能重用。
AQS之countDownLatch原始碼解析
public class countdownlatch int getcount protected int tryacquireshared int acquires protected boolean tryreleaseshared int releases private final syn...
多執行緒 CountDownLatch
countdownlatch 允許乙個或多個執行緒等待其他執行緒完成操作。應用場景 假如有這樣乙個需求,當我們需要解析乙個excel裡多個sheet的資料時,可以考慮使用多執行緒,每個執行緒解析乙個sheet裡的資料,等到所有的sheet都解析完之後,程式需要提示解析完成。在這個需求中,要實現主線程...
執行緒同步 CountDownLatch
應用場景 有乙個任務想要往下執行,但必須要等到其他的任務執行完畢後才可以繼續往下執行。假如我們這個想要繼續往下執行的任務呼叫乙個countdownlatch物件的await 方法,其他的任務執行完自己的任務後呼叫同乙個countdownlatch物件上的countdown 方法,這個呼叫await ...