併發程式設計-柵欄CyclicBarrier
阿新 • • 發佈:2019-02-06
柵欄類似於閉鎖,它能阻塞一組執行緒直到某個事件的發生,當參與的執行緒達到柵欄位置的時候,將會呼叫await()方法,這個將會阻塞當前執行緒直到所有的執行緒全部到達了柵欄。如果所有的執行緒都到達了柵欄,那麼柵欄便會開啟,此時所有的執行緒都會釋放,而柵欄將被重置以便下次使用。
CyclicBarrier有兩個構造器,可選的Runnable 表示的是執行緒通過柵欄的時候執行的程式碼。
其中parities表示的是參與執行緒的個數,當前執行緒在呼叫await()方法的時候會進行阻塞,呼叫await()方法,計數器+1.當計數器等於parities的時候,柵欄便會放開。也就是執行到最後一個參與執行緒,此執行緒呼叫await()方法的時候,所有執行緒同時執行。
CyclicBarrier(int parties)
CyclicBarrier(int parties, Runnable barrierAction)
依舊拿比賽的是事來說吧,這個CyclicBarrier,怎麼玩都可以的。比如下面這個例子是選手準備,然後釋放柵欄,run()方法程式碼執行完表示運動員到達終點。還有例子就是不管開始,只有所有人都完成比賽,可以慶祝之類的。無非是任務的類Runner類裡面的cyclicBarrier.await()位置的問題,選擇CyclicBarrier的第二個構造器即可。
public class Runner implements Runnable{ private CyclicBarrier cyclicBarrier; private int number; public Runner(CyclicBarrier cyclicBarrier, int number) { this.cyclicBarrier = cyclicBarrier; this.number = number; } public void run() { try { System.out.println(number+"th 就位"); cyclicBarrier.await(); System.out.println(number+"th 到達,耗時"+Math.random()*1000); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } }
public class Race {
public static void main(String[] args) {
final int count = 6;
CyclicBarrier cyclicBarrier = new CyclicBarrier(count);
for(int i = 1 ; i <= count ;i++){
new Thread(new Runner(cyclicBarrier,i)).start();
}
}
}
2th 就位 5th 就位 3th 就位 4th 就位 6th 就位 1th 就位 2th 到達,耗時896.3213862018172 3th 到達,耗時571.0326287073248 4th 到達,耗時625.9050513357512 6th 到達,耗時300.6048271390146 1th 到達,耗時706.7176368903195 5th 到達,耗時235.70225351556374
CyclicBarrier有Runnable引數的構造器CyclicBarrier(int parties, Runnable barrierAction),執行緒通過柵欄時,Runnable物件便會被呼叫。
例如:100米的比賽,所有參賽選手都到終點情況下,比賽結束,否則比賽還在進行中。
public class Runner implements Runnable{
private CyclicBarrier cyclicBarrier;
private int number;
public Runner(CyclicBarrier cyclicBarrier, int number) {
this.cyclicBarrier = cyclicBarrier;
this.number = number;
}
public void run() {
try {
System.out.println(number+"th 開跑!");
Thread.sleep(1000);
System.out.println(number+"th 到達!");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
public class Race {
public static void main(String[] args) {
final int count = 6;
CyclicBarrier cyclicBarrier = new CyclicBarrier(count,new Runnable(){
public void run(){
System.out.println("所有人到達終點,該比賽結束了");
}
});
for(int i = 1 ; i <= count ;i++){
new Thread(new Runner(cyclicBarrier,i)).start();
}
}
}
1th 起跑!
3th 起跑!
5th 起跑!
2th 起跑!
4th 起跑!
6th 起跑!
1th 到達!
5th 到達!
3th 到達!
6th 到達!
4th 到達!
2th 到達!
該比賽結束了
第二個例子將cyclicBarrier.await()方法放在Runner的最後,相當於是最後一個執行緒執行到這裡的時候,此時柵欄釋放。所有的 執行緒繼續執行。思想引入自《Java併發程式設計實戰》。