532
技術社區[雲棲]
CyclicBarrier的使用
CyclicBarrier的使用
標簽(空格分隔): Java多線程
簡介
CyclicBarrier的字麵意思是可循環使用(Cyclic)的屏障(Barrier)。CyclicBarrier的作用是讓一組線程之間相互等待,任何一個線程到達屏障點後就阻塞,直到最後一個線程到達,才都繼續往下執行。個人理解:CyclicBarrier可以看成是一道大門或者關卡,先到的線程會被阻塞在大門口,直到最後一個線程到達屏障時,大門才被打開,所有被阻塞的線程才會繼續幹活。就像是朋友聚餐,隻有最後一個朋友到達時,才會開吃!
屏障(Barrier)
CyclicBarrier
的構造函數可以傳入一個整數,其含義是屏障可攔截的線程數,每個線程都可調用await方法告訴CyclicBarrier“我已經到達了屏障前”,CyclicBarrier內部是執行+1操作,一旦屏障前阻塞的線程數等於構造函數傳入的可攔截線程數時,所有被阻塞的線程都將被喚醒,繼續往下執行。
常用API
//parties表示屏障前可阻塞的線程數,當阻塞的線程數到達parties時,屏障被打開,所有阻塞的線程將會被喚醒
public CyclicBarrier(int parties);
// 此構造方法不同於上麵的是在屏障被打開時將優先執行barrierAction,方便處理更負責的業務場景
public CyclicBarrier(int parties, Runnable barrierAction) ;
// 等待屏障的打開
public int await() throws InterruptedException,BrokenBarrierException ;
//等待屏障的打開 超時會拋出 TimeoutException
public int await(long timeout, TimeUnit unit) throws
InterruptedException,
BrokenBarrierException,
TimeoutException ;
// 返回在屏障前等待的線程數
public int getNumberWaiting() ;
// 獲取 當前屏障初始化時 可阻塞的線程數
public int getParties() ;
/**
* 作用:
* 1. 查詢此屏障是否處於損壞狀態。
* 產生損壞狀態的原因:
* 1. 由於超時或者屏障重置(reset)
* 2. 某個屏障操作拋出異常
*/
public boolean isBroken() ;
使用舉例
模擬 聚餐場景
public class CyclicBarrierTest {
public static void main(String[] args) throws Exception{
ExecutorService service = Executors.newFixedThreadPool(3) ;
CyclicBarrier cyclicBarrier = new CyclicBarrier(3,()->{
System.out.println("全都到了 【開吃!】");
}) ;
for(int i = 0 ; i < 3 ; i++) {
final int number = i ;
service.execute(()->{
try {
System.out.println("編號:" + number + "開始出發 【去聚餐】");
Thread.sleep((int)(Math.random() * 10000));
System.out.println("編號:" + number + " 【到達聚餐地點】");
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
});
}
service.shutdown();
}
}
循環使用
循環使用指的是在大門被打開後,可以再次關閉,再次讓之前指定數目的線程在屏障前阻塞等待,然後再次打開大門。
方法reset()的作用就是重置屏障,循環使用。
但是在調用reset()方法後,如果有線程在屏障前等待,則await方法會拋出BrokenBarrierException
異常。這個異常通常發生在當某個線程在等待本CylicBarrier時。https://blog.csdn.net/chenchaofuck1/article/details/51598504
常用API
// 將屏障重置為其初始化狀態即重置為構造函數傳入的parties值。
public void reset();
最後更新:2017-07-27 14:32:48