同步屏障 - CyclicBarrier

CyclicBarrier 是什么剖效?

讓一組線程到達(dá)一個(gè)屏障后被阻塞寺董,直到最后一個(gè)線程到達(dá)屏障時(shí)抄淑,屏障才會(huì)“開門”,所有被屏障阻塞的線程繼續(xù)執(zhí)行馋记。

CyclicBarrier 構(gòu)造

CyclicBarrier(int parties)parties表示屏障攔截的線程數(shù)量号坡,當(dāng)線程調(diào)用await()方法就是告訴CyclicBarrier我已經(jīng)到達(dá)了屏障,然后當(dāng)前線程被阻塞梯醒。
CyclicBarrier(int parties,Runnable barrierAction)
用于在線程到達(dá)屏障時(shí)宽堆,優(yōu)先執(zhí)行barrierAction,方便處理更復(fù)雜的業(yè)務(wù)場(chǎng)景茸习。

CyclicBarrier 方法

類型 方法 描述
int await() 等待直到parties個(gè)線程都調(diào)用了await()
int await(long timeout, TimeUnit unit) 等待直到parties個(gè)線程都調(diào)用了await() 或者過了超時(shí)時(shí)間
int getNumberWaiting() 獲取CyclicBarrier當(dāng)前在等待的線程數(shù)量
int getParties() 獲取CyclicBarrier攔截線程數(shù)量
boolean isBroken() 獲取阻塞的線程是否被中斷
int reset() 將屏障設(shè)置為初始狀態(tài)

CyclicBarrier(int parties)例子

public class CyclicBarrierTest {
    //定義一個(gè)屏障畜隶,設(shè)置攔截兩個(gè)線程
    static CyclicBarrier cyclicBarrier = new CyclicBarrier(2);

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //通知CyclicBarrier我已經(jīng)到達(dá)屏障,線程阻塞
                    cyclicBarrier.await();
                    System.out.println("1");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        System.out.println("2");
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //通知CyclicBarrier我已經(jīng)到達(dá)屏障号胚,線程阻塞
                    cyclicBarrier.await();
                    System.out.println("3");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

輸出結(jié)果

2
3
1

因?yàn)槲覀兌x的CyclicBarrier是攔截兩個(gè)線程籽慢,所以第一個(gè)線程執(zhí)行了await()后開始阻塞,然后繼續(xù)執(zhí)行猫胁,輸出“2”箱亿,當(dāng)?shù)诙€(gè)線程執(zhí)行了await()方法后,第二個(gè)線程達(dá)到屏障弃秆,屏障打開“大門”届惋,兩個(gè)線程繼續(xù)執(zhí)行,輸出“3”和“1”菠赚,也有一種可能是先輸出“1”然后輸出“3”脑豹,這是因?yàn)橹骶€程和子線程的調(diào)度是由CPU決定的,都有可能先執(zhí)行衡查。

CyclicBarrier(int parties,Runnable barrierAction)例子

public class CyclicBarrierTest2 {
    static CyclicBarrier cyclicBarrier = new CyclicBarrier(2, new A());

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    cyclicBarrier.await();
                    System.out.println("1");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        System.out.println("2");
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    cyclicBarrier.await();
                    System.out.println("3");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    static class A implements Runnable {
        @Override
        public void run() {
            System.out.println("4");
        }
    }
}

結(jié)果

2
4
3
1

根據(jù)上面的例子稍微進(jìn)行改造瘩欺,當(dāng)?shù)诙€(gè)線程達(dá)到屏障后,優(yōu)先執(zhí)行了A峡捡,然后阻塞線程才繼續(xù)執(zhí)行击碗。

CyclicBarrier應(yīng)用場(chǎng)景

可以用于多線程計(jì)算數(shù)據(jù),最后合并計(jì)算結(jié)果的場(chǎng)景们拙。

例子

創(chuàng)建一個(gè)屏障稍途,設(shè)置攔截線程數(shù)為10
假設(shè)每個(gè)線程計(jì)算結(jié)果返回1
最終十個(gè)線程計(jì)算結(jié)果相加得到的結(jié)果應(yīng)該為10

package com.sy.thread.example;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CyclicBarrier;

/**
 * Description: thread
 * @author songyu
 */
public class CyclicBarrierTest3 implements Runnable{
    /**
     * 創(chuàng)建屏障
     */
    private CyclicBarrier cyclicBarrier = new CyclicBarrier(10,this::run);
    /**
     * 保存每個(gè)線程執(zhí)行的結(jié)果
     */
    private ConcurrentHashMap<String,Integer> concurrentHashMap = new ConcurrentHashMap<>();
    private void calculationData() {
        //使用線程不規(guī)范,實(shí)際使用時(shí)可以使用ThreadPoolExecutor
        for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    concurrentHashMap.put(Thread.currentThread().getName(),1);
                    try {
                        cyclicBarrier.await();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }

    @Override
    public void run() {
        int result = 0;
        for (Map.Entry<String, Integer> map : concurrentHashMap.entrySet()) {
            result = result + map.getValue();
        }
        System.out.println("最終計(jì)算結(jié)果:" + result);
    }

    public static void main(String[] args) {
        CyclicBarrierTest3 c = new CyclicBarrierTest3();
        c.calculationData();
    }

}

結(jié)果

最終計(jì)算結(jié)果:10
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末砚婆,一起剝皮案震驚了整個(gè)濱河市械拍,隨后出現(xiàn)的幾起案子突勇,更是在濱河造成了極大的恐慌,老刑警劉巖坷虑,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件甲馋,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡迄损,警方通過查閱死者的電腦和手機(jī)定躏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來芹敌,“玉大人痊远,你說我怎么就攤上這事∈侠蹋” “怎么了碧聪?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)液茎。 經(jīng)常有香客問我逞姿,道長(zhǎng),這世上最難降的妖魔是什么捆等? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任滞造,我火速辦了婚禮,結(jié)果婚禮上楚里,老公的妹妹穿的比我還像新娘断部。我一直安慰自己猎贴,他們只是感情好班缎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著她渴,像睡著了一般达址。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上趁耗,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天沉唠,我揣著相機(jī)與錄音,去河邊找鬼苛败。 笑死满葛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的罢屈。 我是一名探鬼主播嘀韧,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼缠捌!你這毒婦竟也來了锄贷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谊却,沒想到半個(gè)月后柔昼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡炎辨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年捕透,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碴萧。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡激率,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出勿决,到底是詐尸還是另有隱情乒躺,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布低缩,位于F島的核電站嘉冒,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏咆繁。R本人自食惡果不足惜讳推,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望玩般。 院中可真熱鬧银觅,春花似錦、人聲如沸坏为。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽匀伏。三九已至洒忧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間够颠,已是汗流浹背熙侍。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留履磨,地道東北人蛉抓。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像剃诅,于是被迫代替她去往敵國(guó)和親巷送。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355