閱讀532 返回首頁    go 技術社區[雲棲]


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

  上一篇:go  大數據時代審計技術方法的發展趨勢
  下一篇:go  大數據加速滲透醫療行業 醫療護理將顯著受益