乙個多執行緒協同器,它可以讓一組執行緒相互等待,當等待的數量達到預設數量時這組執行緒通過等待繼續工作。說得形象點,cyclicbarrier就好比汽車站滾動發車的模式,把客車看著cyclicbarrier,乘客看著是各個任務執行緒,當乘客到達客車時,需要等待另外的乘客,當乘客到齊後自動發車,如果等待乘客超時了,則將乘客全部趕下車(司機太**了),然後重新安排依次上車(是否要上車由乘客自己決定);每個上車的乘客都需要判斷自己是否是這輛車的最後乙個乘客,如果不是,則上車後立即開始睡覺,如果是最後乙個,則他需要叫醒所有乘客。當然客車站在建立這些客車的時候可能會做一些額外的事情,例如所有乘客到齊後,司機給大夥一人發一瓶礦泉水,或者是其它的,但是前提條件就是乘客到齊。
圖中的cyclicbarrier需要等待8個執行緒到達後才會「發車」,目前已經到達的執行緒有4個,還需要等待4個執行緒;執行緒上車的過程(也就是進入await的過程)是要進行排隊的,這裡是通過reentrantlock來實現的,上車後的睡眠是通過鎖的條件等待condition來實現的。
public
class
cyclicbarrier
//執行緒進入條件等待時需要獲取鎖
private
final reentrantlock lock =
newreentrantlock()
;//等待條件
private
final condition trip = lock.
newcondition()
;//每次需要協同的執行緒數(客車的準載數)
private
final
int parties;
//這組執行緒(parties)滿足協同條件後需要做的一件事情
private
final runnable barriercommand;
//標識例項,乙個generation代表一次執行緒協同
private generation generation =
newgeneration()
;//還需要等待的執行緒數量(還未上車的乘客數)
private
int count;
//最後乙個乘客上車後使用的工具,喚醒所有乘客,
private
void
nextgeneration()
//等待超時後,司機生氣了,就用這個方法把大家叫醒,然後把這輛車標記為broken,把所有人趕下車
private
void
breakbarrier()
//車輛的構造器,客車佔為車輛設定的規則
public
cyclicbarrier
(int parties, runnable barrieraction)
//同上,只是執行緒協同完成後不需要做額外的動作
public
cyclicbarrier
(int parties)
/** 一些核心方法
**/}
cyclicbarrier的核心方法是await,該方法是執行緒相互等待的關鍵,它有兩種實現,一種是帶等待超時的,一種是不會等待超時:
public
intawait()
throws interruptedexception, brokenbarrierexception
catch
(timeoutexception toe)
}public
intawait
(long timeout, timeunit unit)
throws interruptedexception, brokenbarrierexception,timeoutexception
從**可以看出,其核心都是使用了dowait這個方法
private
intdowait
(boolean timed,
long nanos)
throws interruptedexception, brokenbarrierexception,
timeoutexception
int index =
--count;
//上車成功,還需要上車的人數減1
if(index ==0)
finally
}//如果上車的不是最後乙個乘客
for(;;
)catch
(interruptedexception ie)
else}if
(g.broken)
throw
newbrokenbarrierexception()
;//被標記為了broken(這可能自己前面標的,也可能其它執行緒標的),則所有的執行緒都丟擲異常。
if(g != generation)
//如果是正常被喚醒,則直接返回還需上車的人(理論上應該是0)
return index;
if(timed && nanos <=
0l)}
}finally
}
從**可以看出,cyclicbarrier的實現是利用條件等待,用到條件等待當然就會用到鎖。
多個執行緒協調過程中,只要有乙個執行緒被中斷或者發生異常,則整個協調取消。
相同點:
1.都能讓多個執行緒協調,在某乙個點上等待
不同點:
1.cyclicbarrier是多個執行緒自行協同,當執行緒到達等待數量時自動放行,而countdownlatch是多個執行緒阻塞後,需要外界條件達到某種狀態的時候才會被統一喚醒,即cyclicbarrier只需要各個執行緒await,而countdownlatch還需要額外是countdown。
2.實現上,cyclicbarrier是使用獨佔鎖+condition實現的,而countdownlatch是自己實現aqs,利用共享鎖的原理實現。
3.countdownlatch一旦滿足條件後需要重新初始化才能再使用,而cyclicbarrier可以迴圈使用。
併發程式設計之 CyclicBarrier 原始碼分析
在之前的介紹 countdownlatch 的文章中,countdown 可以實現多個執行緒協調,在所有指定執行緒完成後,主線程才執行任務。但是,countdownlatch 有個缺陷,這點 jdk 的文件中也說了 他只能使用一次。在有些場合,似乎有些浪費,需要不停的建立 countdownlatc...
AbstractCollection原始碼分析
abstractcollection抽象類提供了collection的骨架實現,collection分析請看 這裡直接看它的 是如何實現的.public abstract iterator iterator 該方法沒有實現.public abstract int size 該方法沒有實現.publi...
ThreadPoolExecutor原始碼閱讀
執行緒池解決兩個問題 一是復用執行緒,減少建立銷毀執行緒帶來系統開銷 二是限定系統資源使用邊界,避免大量執行緒消耗盡系統記憶體 適用於互不依賴,執行時間短,不需要對執行緒控制操作的執行緒 新增任務時,1.若執行緒數量小於corepoolsize,則新增執行緒執行任務 2.若執行緒數量大於等於core...