Java的幾個同步輔助類

Java為我們提供了一些同步輔助類悯嗓,利用這些輔助類我們可以在多線程編程中瓷叫,靈活地把握線程的狀態(tài)妄辩。

CountDownLatch

CountDownLatch一個同步輔助類春瞬,在完成一組正在其他線程中執(zhí)行的操作之前,它允許一個或多個線程一直等待鸭津。

再CountDownLatch中兩個比較關鍵的方法:

public void await() throws InterruptedException;
public void countDown();

CountDownLatch是一個計數(shù)器彤侍,它的構造方法中需要設置一個數(shù)值,用來設定計數(shù)的次數(shù)逆趋。每次調(diào)用countDown()方法之后盏阶,這個計數(shù)器都會減去1,CountDownLatch會一直阻塞著調(diào)用await()方法的線程闻书,直到計數(shù)器的值變?yōu)?code>0名斟。

設想有這樣一個功能需要Thread1、Thread2魄眉、Thread3砰盐、Thread4四條線程分別統(tǒng)計C、D坑律、E岩梳、F四個盤的大小,所有線程都統(tǒng)計完畢交給主線程去做匯總,利用CountDownLatch來完成就非常輕松蒋腮。

public class CountDownLatchTest {

    private static CountDownLatch count = new CountDownLatch(4);
    private static ExecutorService service = Executors.newFixedThreadPool(6);

    public static void main(String args[]) throws InterruptedException {

        for (int i = 0; i < 4; i++) {
            service.execute(() -> {
                // 模擬任務耗時
                try {
                    int timer = new Random().nextInt(5);
                    TimeUnit.SECONDS.sleep(timer);
                    System.out.printf("%s時完成磁盤的統(tǒng)計任務,耗費%d秒.\n", new Date().toString(), timer);
                    // 任務完成之后,計數(shù)器減一
                    count.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        // 主線程一直被阻塞,知道count的計數(shù)器被設置為0
        count.await();

        System.out.printf("%s時全部任務都完成,執(zhí)行合并計算.\n", new Date().toString());
        service.shutdown();
    }
}

CyclicBarrier

Barrier在英語中是屏障的意思淘捡,這個同步工具會阻塞調(diào)用的線程藕各,直到條件滿足時池摧,阻塞的線程同時被打開。

public int await() throws InterruptedException, BrokenBarrierException

CyclicBarrier初始化的時候激况,設置一個屏障數(shù)作彤。線程調(diào)用await()方法的時候,這個線程就會被阻塞乌逐,當調(diào)用await()的線程數(shù)量到達屏障數(shù)的時候竭讳,主線程就會取消所有被阻塞線程的狀態(tài)。

CyclicBarrier的構造方法中浙踢,還可以設置一個barrierAction绢慢。

在所有的屏障都到達之后,會啟動一個線程來運行這里面的代碼洛波。這里舉一個例子:百米賽跑的運動員起跑前需要準備胰舆,所有選手準備完畢之后,才可以同時起跑蹬挤。

public class CyclicBarrierTest {

    private static CyclicBarrier cyclicBarrier = new CyclicBarrier(8);
    private static ExecutorService service = Executors.newFixedThreadPool(50);

    public static void main(String args[]) {
        for (int i = 1; i < 9; i++) {
            service.execute(new Thread(new Runner(i, cyclicBarrier)));
        }
        service.shutdown();
    }
}
// 運動員類
public class Runner implements Runnable {

    private int number;
    private CyclicBarrier cyclicBarrier;

    public Runner(int number, CyclicBarrier cyclicBarrier) {
        this.number = number;
        this.cyclicBarrier = cyclicBarrier;
    }

    @Override
    public void run() {
        try {
            int timer = new Random().nextInt(5);
            TimeUnit.SECONDS.sleep(timer);
            System.out.printf("%d號選手準備完畢,準備時間%d\n", number, timer);
            cyclicBarrier.await();
            System.out.printf("%d號選手于%s時起跑!\n", number, new Date().toString());
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

輸出:

1號選手準備完畢,準備時間0
4號選手準備完畢,準備時間0
5號選手準備完畢,準備時間1
8號選手準備完畢,準備時間1
3號選手準備完畢,準備時間2
2號選手準備完畢,準備時間3
7號選手準備完畢,準備時間3
6號選手準備完畢,準備時間3
7號選手于Sun Mar 27 21:19:00 CST 2016時起跑!
2號選手于Sun Mar 27 21:19:00 CST 2016時起跑!
5號選手于Sun Mar 27 21:19:00 CST 2016時起跑!
6號選手于Sun Mar 27 21:19:00 CST 2016時起跑!
3號選手于Sun Mar 27 21:19:00 CST 2016時起跑!
8號選手于Sun Mar 27 21:19:00 CST 2016時起跑!
4號選手于Sun Mar 27 21:19:00 CST 2016時起跑!
1號選手于Sun Mar 27 21:19:00 CST 2016時起跑!

相比CountDownLatch缚窿,CyclicBarrier是可以被循環(huán)使用的,而且遇到線程中斷等情況時焰扳,還可以利用reset()方法倦零,重置計數(shù)器,從這些方面來說吨悍,CyclicBarrier會比CountDownLatch更加靈活一些扫茅。

Semaphore

Semaphore被用于控制特定資源在同一個時間被訪問的個數(shù)。類似連接池的概念育瓜,保證資源可以被合理的使用葫隙。

Semaphore的幾個重要方法:

// 獲取資源
public void acquire() throws InterruptedException
// 釋放資源
public void release()

Semaphore的構造方法可以設置一個int值來設置一個計數(shù)器,用于表示資源同時可以被多少外部環(huán)境使用爆雹。每使用一次acquire()停蕉,計數(shù)器都會去減去一,而每次調(diào)用release()計數(shù)器則會增加一钙态。當計數(shù)器的值為0的時候慧起,外部的環(huán)境被阻塞,直到Semaphore有空閑的資源可以被使用册倒。

public class SemaphoreTest {

    private static Semaphore semaphore = new Semaphore(3);
    private static ExecutorService service = Executors.newFixedThreadPool(6);

    public static void main(String args[]) {

        // 執(zhí)行9個任務
        for (int i = 0; i < 9; i++) {
            service.execute(() -> {
                try {
                    semaphore.acquire();
                    System.out.printf("%s時獲取資源,并調(diào)用.\n", new Date().toString());
                    // 線程掛起3秒
                    TimeUnit.SECONDS.sleep(3);
                    semaphore.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        service.shutdown();
    }
}

運行的結果就是:

Sun Mar 27 20:18:16 CST 2016時獲取資源,并調(diào)用.
Sun Mar 27 20:18:16 CST 2016時獲取資源,并調(diào)用.
Sun Mar 27 20:18:16 CST 2016時獲取資源,并調(diào)用.
Sun Mar 27 20:18:19 CST 2016時獲取資源,并調(diào)用.
Sun Mar 27 20:18:19 CST 2016時獲取資源,并調(diào)用.
Sun Mar 27 20:18:19 CST 2016時獲取資源,并調(diào)用.
Sun Mar 27 20:18:22 CST 2016時獲取資源,并調(diào)用.
Sun Mar 27 20:18:22 CST 2016時獲取資源,并調(diào)用.
Sun Mar 27 20:18:22 CST 2016時獲取資源,并調(diào)用.

雖然線程池允許6個最大線程數(shù)量蚓挤,但是同一個時間內(nèi)只用三個任務被執(zhí)行。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市灿意,隨后出現(xiàn)的幾起案子估灿,更是在濱河造成了極大的恐慌,老刑警劉巖缤剧,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件馅袁,死亡現(xiàn)場離奇詭異,居然都是意外死亡荒辕,警方通過查閱死者的電腦和手機汗销,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抵窒,“玉大人弛针,你說我怎么就攤上這事±罨剩” “怎么了削茁?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長掉房。 經(jīng)常有香客問我茧跋,道長,這世上最難降的妖魔是什么圃阳? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任厌衔,我火速辦了婚禮,結果婚禮上捍岳,老公的妹妹穿的比我還像新娘富寿。我一直安慰自己,他們只是感情好锣夹,可當我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布页徐。 她就那樣靜靜地躺著,像睡著了一般银萍。 火紅的嫁衣襯著肌膚如雪变勇。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天贴唇,我揣著相機與錄音搀绣,去河邊找鬼。 笑死戳气,一個胖子當著我的面吹牛链患,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播瓶您,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼麻捻,長吁一口氣:“原來是場噩夢啊……” “哼纲仍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起贸毕,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤郑叠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后明棍,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乡革,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年击蹲,在試婚紗的時候發(fā)現(xiàn)自己被綠了署拟。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡歌豺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出心包,到底是詐尸還是另有隱情类咧,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布蟹腾,位于F島的核電站痕惋,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏娃殖。R本人自食惡果不足惜值戳,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望炉爆。 院中可真熱鬧堕虹,春花似錦、人聲如沸芬首。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽郁稍。三九已至赦政,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間耀怜,已是汗流浹背恢着。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留财破,地道東北人掰派。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像狈究,于是被迫代替她去往敵國和親碗淌。 傳聞我的和親對象是個殘疾皇子盏求,可洞房花燭夜當晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內(nèi)容