二、Java多執行緒併發同步之CyclicBarrier
阿新 • • 發佈:2019-01-01
概述
CyclicBarrier:可迴圈屏障,允許一組執行緒全部等待的同步輔助工具。一組執行緒互相等待,直到所有執行緒都到達某個公共屏障點(也可以叫同步點) 。它可以在等待執行緒之後重新使用。這個屏障之所以用迴圈修飾,是因為在所有的執行緒釋放彼此之後,這個屏障是可以重新使用的 。
CyclicBarrier支援一個可選的Runnable命令,在一組執行緒中的最後一個執行緒到達屏障點之後(但在釋放所有執行緒之前),該命令只在所有執行緒到達屏障點之後執行一次,並且該命令由最後一個進入屏障點的執行緒執行。
業務場景
需要所有的子任務都完成時,才執行主任務,這個時候就可以選擇使用CyclicBarrier。 例如,多執行緒計算資料,最後合併彙總計算的場景;長途汽車等人到齊了才發車的場景,王者榮耀5V5時,需要10個人的進度都為100%時才能進入遊戲等等場景都可以使用CyclicBarrier實現。
下面介紹一個5個人約好去五星級大酒店聚餐場景:5個人約好去聚餐,由於每個人家到酒店的距離不一樣,所以需要等所有人到齊後,才能開餐吃飯,並且規定誰最後一個到,就請大家一起去按摩,然後去吃飯。
實現
CyclicBarrier(int parties):建立一個給定數量執行緒的迴圈屏障,當到達同步點時,不執行預先定義的動作
CyclicBarrier(int parties, Runnable barrierAction):建立一個給定數量執行緒的迴圈屏障,當到達同步點時,執行 Runnable方法
await():進行阻塞等待 ,直到滿足下列條件時,繼續執行:
- 等待的執行緒數達到parties時,所有到達的執行緒將被釋放,繼續向下執行。
- 當前執行緒被中斷,丟擲InterruptedException異常,並停止等待,繼續執行。
- 其他等待的執行緒被中斷(interrupt),當前執行緒會丟擲BrokenBarrierException異常,並停止等待,繼續執行。
- 其他等待的執行緒超時,當前執行緒會丟擲BrokenBarrierException異常,並停止等待,繼續執行。
- 其他執行緒呼叫reset()方法,當前執行緒會丟擲BrokenBarrierException異常,並停止等待,繼續執行。
reset():重置,使CyclicBarrier迴歸初始狀態
getNumberWaiting():獲取正在等待的執行緒數量。
/**
* CyclicBarrier : 可迴圈的屏障,讓一組執行緒到達一個同步點後再一起繼續執行,在其中任意一個執行緒未達到同步點,其他到達的執行緒均會被阻塞。
* 業務場景: 5個人約好去五星級大酒店聚餐
*/
public class CyclicBarrierTest implements Runnable {
private ExecutorService es = Executors.newCachedThreadPool();
private CyclicBarrier cyclicBarrier = new CyclicBarrier(5, this); // 攔截執行緒為5
//達到同步點後執行方法
@Override
public void run() {
System.out.println("吃飯前先一起去按摩");
}
//實現任務
public void invoke() {
// 5個執行緒,模擬5個人
for (int i = 0; i < 5; i++) {
final String user = "user"+(i+1);
es.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep((long)(Math.random()*10000)); //模擬去酒店,每個人都不一樣
System.out.println(user+"---到達酒店,當前有"+(cyclicBarrier.getNumberWaiting()+1)+"個人到達");
cyclicBarrier.await(); // 等待所有人到酒店
System.out.println(user + "---所有人到齊,吃飯去了。。。");
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
public static void main(String[] args) {
CyclicBarrierTest service = new CyclicBarrierTest();
service.invoke();
}
}
輸出結果:
user4---到達酒店,當前有1個人到達
user2---到達酒店,當前有2個人到達
user3---到達酒店,當前有3個人到達
user1---到達酒店,當前有4個人到達
user5---到達酒店,當前有5個人到達
吃飯前先一起去按摩
user5---所有人到齊,吃飯去了。。。
user4---所有人到齊,吃飯去了。。。
user1---所有人到齊,吃飯去了。。。
user3---所有人到齊,吃飯去了。。。
user2---所有人到齊,吃飯去了。。。