CyclicBarrier原始碼理解

2021-10-07 09:36:24 字數 3182 閱讀 1572

一、cyclicbarrier介紹

乙個批次的執行緒都到達某種狀態(呼叫cyclicbarrier.await方法)後,再執行另乙個任務(由最後乙個呼叫await方法的執行緒執行)。

同時,它是可以重複使用的,通過重置狀態;而countdownlatch是不能重複用的;

二、原理

建立cyclicbarrier例項時,指定執行緒數量和後續任務(也可以不指定這個任務),呼叫await()方法進行等待,await方法內部使用reentrantlock,對等待中的執行緒數量減1,當等待中的執行緒數量為0時,則執行指定的後續任務,再執行阻塞執行緒後續的**。

1、屬性介紹

//記錄柵欄的年代資訊。當所有執行緒通行或者柵欄被重置的時候,會產生乙個新的年代。

//因為cyclicbarrier可以重複使用,因此每乙個generation物件,就代表了一次cyclicbarrier的使用。

private static class generation

//柵欄鎖

private final reentrantlock lock = new reentrantlock();

private final condition trip = lock.newcondition();

//匯流排程數量

private final int parties;

//所有執行緒都到達後,要執行的任務

private final runnable barriercommand;

//當前柵欄的年代資訊

private generation generation = new generation();

//等待中的執行緒數量。其值為0-parties之間。當柵欄被破壞或重置柵欄時,其值更新為parties。

private int count;

2、建構函式

//傳入執行緒數量和指定的任務,初始化parties和count

public cyclicbarrier(int parties, runnable barrieraction)

public cyclicbarrier(int parties)

3、await()方法:呼叫後執行緒進入等待,直到所有的執行緒都到達。

//執行緒進入等待狀態,該方法還有超時引數版本。

public int await() throws interruptedexception, brokenbarrierexception catch (timeoutexception toe)

}//主要方法

private int dowait(boolean timed, long nanos)

throws interruptedexception, brokenbarrierexception,

timeoutexception

//等待的執行緒數量減1,當最後乙個執行緒到達(也就是等待的執行緒數量為0時),就執行指定的任務,然後通知所有等待中的執行緒恢復執行、重置count的值。

int index = --count;

if (index == 0) finally

}// 到這裡,說明count != 0,還有執行緒沒有到達,所以先到達的執行緒需要阻塞等待。

for (;;) catch (interruptedexception ie) else

}if (g.broken)

throw new brokenbarrierexception();

if (g != generation)

return index;

if (timed && nanos <= 0l)

}} finally

}//通知等待中的執行緒繼續執行、重置count的值、建立新的generation

private void nextgeneration()

//銷毀柵欄(設定broken為true)、重置count、通知所有等待的執行緒繼續執行

private void breakbarrier()

4、isbroken():判斷當前柵欄是否被銷毀,broken的值會影響await()方法的執行

public boolean isbroken()  finally 

}

5、reset():重置柵欄,觸發的動作主要包括:銷毀柵欄(broken=true)、通知所有阻塞的執行緒(在await方法裡,在接收到notifyall方法後,會判斷broken的值,為true則丟擲異常)、重置count,建立新的generation。

public void reset()  finally 

}

三、示例

public class cyclicbarriertest 

@override

public void run() catch (interruptedexception e) catch (brokenbarrierexception e)

system.out.println(thread.currentthread().getname() + "end wait");}}

public static void main(string args)

system.out.println("main執行緒結束");

}}

執行結果:

thread-0start wait

main執行緒結束

thread-1start wait

thread-3start wait

thread-4start wait

thread-2start wait

thread-2, 所有執行緒結束

thread-2end wait

thread-4end wait

thread-3end wait

thread-1end wait

thread-0end wait

結果分析:

1、主線程和新建立的5個執行緒沒有等待關係,這點與countdownlatch不同,在countdownlatch使用中,一般是在主線程中呼叫await()方法進行等待,等所有執行緒都執行完後,再執行主線程。

2、所有執行緒都到達後,先執行指定的後續任務,再繼續阻塞後的執行緒**。

併發程式設計之 CyclicBarrier 原始碼分析

在之前的介紹 countdownlatch 的文章中,countdown 可以實現多個執行緒協調,在所有指定執行緒完成後,主線程才執行任務。但是,countdownlatch 有個缺陷,這點 jdk 的文件中也說了 他只能使用一次。在有些場合,似乎有些浪費,需要不停的建立 countdownlatc...

AbstractCollection原始碼分析

abstractcollection抽象類提供了collection的骨架實現,collection分析請看 這裡直接看它的 是如何實現的.public abstract iterator iterator 該方法沒有實現.public abstract int size 該方法沒有實現.publi...

ThreadPoolExecutor原始碼閱讀

執行緒池解決兩個問題 一是復用執行緒,減少建立銷毀執行緒帶來系統開銷 二是限定系統資源使用邊界,避免大量執行緒消耗盡系統記憶體 適用於互不依賴,執行時間短,不需要對執行緒控制操作的執行緒 新增任務時,1.若執行緒數量小於corepoolsize,則新增執行緒執行任務 2.若執行緒數量大於等於core...