NO IMAGE

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

本文依然以《天龍八部》四大惡人舉例。

縱覽整本小說,四大惡人為了準備殺段正淳集結在大理,為了殲滅丐幫集結在杏子林,為了少室山大戰集結在少室山….

我們發現,四大惡人僅僅一次集合是不夠的!也就是說,這“四個執行緒”僅僅併發協作一次不夠的!

但是CountDownLatch卻是一次性的併發工具。由此,CyclicBarrier有了勇武之地。

/*
CyclicBarrier迴圈屏障
用途:協同指定數目的執行緒,讓這些執行緒在這個屏障前等待,知道所有執行緒都到達了這個屏障,在一起繼續執行。執行緒繼續執行後,這個屏障可再次使用,因此為迴圈屏障。
*/
public class CyclicBarrier {
//構造方法
//parties:制定多有少個部分(執行緒)參與,被稱為參與數。
public CyclicBarrier(int parties){...}
//構造方法
/*
barrierAction:所有參與者都達到屏障時執行的一次的命令,在一組執行緒中的最後一個執行緒達到之後(但在釋放所有執行緒之前),在該執行緒中執行該命令,該命令只在每個屏障點執行一次。若要在繼續執行所有參與執行緒之前更新共享狀態,此屏障操作很有用!
*/
public CyclicBarrier(int parties , Runnable barrierAction){...}
//等待方法
/*
執行緒執行過程中呼叫await()方法,表明自己已達到屏障,自己阻塞,等待其他執行緒到達屏障;所有參與執行緒都到達屏障,即等待執行緒數==參與者,則釋放所有執行緒,讓他們繼續執行。
返回int值是到達的當前執行緒的索引號,注意索引號是從parties-1開始遞減到0。
BrokenBarrierExcepyion:屏障被破壞異常,當呼叫await時,或等待過程中屏障被破壞,則會丟擲該異常。
*/
public int await() throws InterruptedException, BrokenBarrierException {...}
//以下方法不做重點討論
//等待指定時長,如到了時間還不能釋放,則將丟擲TimeoutException
public int await(long timeout, TimeUnit unit)
throws InterruptedException,
BrokenBarrierException,
TimeoutException {...}
//獲取當前等在屏障處的執行緒數
public int getNumberWaiting() {}
//判斷執行緒是否被破壞
public boolean isBroken() {}    
//重置屏障為初始狀態。如果當前有執行緒正在等待,則這些執行緒將被釋放並丟擲BrokenBarrierException
public void reset() {}
}

CyclicBarrier使用注意事項:

一定要保證有足夠的參與者執行緒,否則會一直被阻塞在屏障處。

線上程池中使用要更加小心!確保池的執行緒數>=要求的參與數

CyclicBarrier適用場景:

等待一起出發。

多次等待一起出發。

        CyclicBarrier cyclicBarrier = new CyclicBarrier(4);
for(int i = 0 ; i < 4 ; i  ) {
new Thread((i   1)   ""){
@Override
public void run() {
System.out.println("大理城天下第"   this.getName()   "大惡人到了");
cyclicBarrier.await();
System.out.println("杏子林天下第"   this.getName()   "大惡人到了");
cyclicBarrier.await();
System.out.println("少室山天下第"   this.getName()   "大惡人到了");
}
}.start();
}

注:為了美觀await()方法沒有加try-catch

 

CyclicBarrier和CountDownLatch的區別:

CountDownLatch:是一部分執行緒等待另一部分執行緒來喚醒。

CyclicBarrier:是參與執行緒彼此等待,都到達了,在一起繼續。

CountDownLatch不可迴圈使用,都到達了,在一起繼續。