多執行緒-併發:介紹Phaser

接上一篇。多執行緒-併發:介紹CyclicBarrier

我們繼續聊《天龍八部》四大惡人。

大家都知道,葉二孃是虛竹的娘,少室山一戰玄慈方丈和葉二孃都領了便當。從此四大惡人就剩了三個。

大家也都知道,小說接近尾聲,段譽身份解開前後,嶽老三被段延慶捅了個透心涼領了便當;雲中鶴因為中了悲酥清風,被前來救援的大理臣子收了人頭。從此四大惡人就剩了一個。

當我們縱觀整個四大惡人(四個執行緒),發現他們:

①多階段協同,但階段的參與數可變!因此在使用CyclicBarrier不好實現了。

②假定第一階段4個,第二階段3個,第三階段1個。

這時,就需要我們有新的程式設計利器:Phaser(階段協同器,也被稱為相位器)

簡介:

java7中增加的用於多階段同步控制的工具類,它包含了CyclicBarrier和CountDownLatch的相關功能,比他們更加強大靈活。

多個執行緒寫作執行的任務分為多個階段,每個階段都可以有任意個參與者,執行緒可以隨時註冊並參與到某個階段;當一個階段中所有的任務都被完成成功之後,Phaser的OnAdvance()被呼叫(類似迴圈屏障的使用的Runnable介面,可以通過覆蓋新增自定義處理邏輯),然後Phaser釋放等待執行緒,自動進入下個階段。如此迴圈,直到Phaser不再包含任何參與者。

//注意!
//單個Phaser示例允許的註冊任務數上限65535,如果參與任務數操作,可用父子Phaser樹的方式
public class Phaser {
//構造方法
//參與任務數為0
public Phaser() {...}
//制定初始參與任務數
//public Phaser(int parties) {...}
//指定父容器。子物件整體作為一個參與者加入到父物件,當子物件中沒有參與者時,自動從父物件解除註冊
public Phaser(Phaser parent) {...}
public Phaser(Phaser parent, int parties) {...}
//增減參與任務數方法
//增加一個數,返回當前階段號
public int register() {...}
//增加指定個數,返回當前階段號
public int bulkRegister(int parties) {...}
//減少一個任務數,返回當前階段號
public int arriveAndDeregister() {...}
//到達、等待方法
//到達(任務完成),返回當前階段號
public int arrive() {...}
//到達後等待其他任務到達,返回到達階段號
public int arriveAndAwaitAdvance() {...}
//在指定階段等待(必須是當前階段才有效)
public int awaitAdvance(int phase) {...}
public int awaitAdvanceInterruptibly(int phase){...}
public int awaitAdvanceInterruptibly(int phase,
long timeout, TimeUnit unit){...}
//階段到達觸發動作
//類似CyclicBarrier觸發命令,通過重寫該方法來增加階段到達動作,該方法返回true將終結Phaser物件
protected boolean onAdvance(int phase, int registeredParties) {...}
//其他API
//強制結束
public void forceTermination() {...}
//獲取當前階段號
public final int getPhase() {...}
//判斷是否結束
public boolean isTerminated() {...}
}

如圖:

好了,在最後,我們總結以下CountDownLatch、CyclicBarrier、Phaser的使用:

1.等待N個條件到達:CountDownLatch、Phaser

2.等待一起出發:CountDownLatch、CyclicBarrier、Phaser

3.不變參與數,多階段等待一起出發:CyclicBarrier、Phaser

4.可變參與數,多階段等待一起出發:Phaser