一、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...