Java并發(fā)編程(CyclicBarrier)實(shí)例詳解
Java并發(fā)編程(CyclicBarrier)實(shí)例詳解
前言:
使用JAVA編寫(xiě)并發(fā)程序的時(shí)候,我們需要仔細(xì)去思考一下并發(fā)流程的控制,如何讓各個(gè)線程之間協(xié)作完成某項(xiàng)工作。有時(shí)候,我們啟動(dòng)N個(gè)線程去做一件事情,只有當(dāng)這N個(gè)線程都達(dá)到某一個(gè)臨界點(diǎn)的時(shí)候,我們才能繼續(xù)下面的工作,就是說(shuō)如果這N個(gè)線程中的某一個(gè)線程先到達(dá)預(yù)先定義好的臨界點(diǎn),它必須等待其他N-1線程也到達(dá)這個(gè)臨界點(diǎn),接下來(lái)的工作才能繼續(xù),只要這N個(gè)線程中有1個(gè)線程沒(méi)有到達(dá)所謂的臨界點(diǎn),其他線程就算搶先到達(dá)了臨界點(diǎn),也只能等待,只有所有這N個(gè)線程都到達(dá)臨界點(diǎn)后,接下來(lái)的事情才能繼續(xù)。
一、場(chǎng)景描述
有四個(gè)游戲玩家玩游戲,游戲有三個(gè)關(guān)卡,每個(gè)關(guān)卡必須要所有玩家都到達(dá)后才能允許通過(guò)。其實(shí)這個(gè)場(chǎng)景里的玩家中如果有玩家A先到了關(guān)卡1,他必須等到其他所有玩家都到達(dá)關(guān)卡1時(shí)才能通過(guò),也就是說(shuō)線程之間需要相互等待。這和CountDownLatch的應(yīng)用場(chǎng)景有區(qū)別,CountDownLatch里的線程是到了運(yùn)行的目標(biāo)后繼續(xù)干自己的其他事情,而這里的線程需要等待其他線程后才能繼續(xù)完成下面的工作。
二、CyclicBarrier介紹
CyclicBarrier 的字面意思是可循環(huán)使用(Cyclic)的屏障(Barrier)。它要做的事情是,讓一組線程到達(dá)一個(gè)屏障(也可以叫同步點(diǎn))時(shí)被阻塞,直到最后一個(gè)線程到達(dá)屏障時(shí),屏障才會(huì)開(kāi)門(mén),所有被屏障攔截的線程才會(huì)繼續(xù)干活。CyclicBarrier默認(rèn)的構(gòu)造方法是CyclicBarrier(int parties),其參數(shù)表示屏障攔截的線程數(shù)量,每個(gè)線程調(diào)用await方法告訴CyclicBarrier我已經(jīng)到達(dá)了屏障,然后當(dāng)前線程被阻塞。
CyclicBarrier類有兩個(gè)常用的構(gòu)造方法:
1. CyclicBarrier(int parties)
這里的parties也是一個(gè)計(jì)數(shù)器,例如,初始化時(shí)parties里的計(jì)數(shù)是3,于是擁有該CyclicBarrier對(duì)象的線程當(dāng)parties的計(jì)數(shù)為3時(shí)就喚醒,注:這里parties里的計(jì)數(shù)在運(yùn)行時(shí)當(dāng)調(diào)用CyclicBarrier:await()時(shí),計(jì)數(shù)就加1,一直加到初始的值
2. CyclicBarrier(int parties, Runnable barrierAction)
這里的parties與上一個(gè)構(gòu)造方法的解釋是一樣的,這里需要解釋的是第二個(gè)入?yún)?Runnable barrierAction),這個(gè)參數(shù)是一個(gè)實(shí)現(xiàn)Runnable接口的類的對(duì)象,也就是說(shuō)當(dāng)parties加到初始值時(shí)就出發(fā)barrierAction的內(nèi)容。
代碼示例
package com.itmyhome; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; /** * 玩家類 * @author itmyhome * */ class Player implements Runnable { private CyclicBarrier cyclicBarrier; private int id; public Player(int id, CyclicBarrier cyclicBarrier) { this.cyclicBarrier = cyclicBarrier; this.id = id; } @Override public void run() { try { System.out.println("玩家" + id + "正在玩第一關(guān)..."); cyclicBarrier.await(); System.out.println("玩家" + id + "進(jìn)入第二關(guān)..."); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } } public class CyclicBarrierTest { public static void main(String[] args) { // CyclicBarrier cyclicBarrier = new CyclicBarrier(4); CyclicBarrier cyclicBarrier = new CyclicBarrier(4, new Runnable() { @Override public void run() { System.out.println("所有玩家進(jìn)入第二關(guān)!"); } }); for (int i = 0; i < 4; i++) { new Thread(new Player(i, cyclicBarrier)).start(); } } }
輸出結(jié)果:
玩家0正在玩第一關(guān)... 玩家3正在玩第一關(guān)... 玩家2正在玩第一關(guān)... 玩家1正在玩第一關(guān)... 所有玩家進(jìn)入第二關(guān)! 玩家3進(jìn)入第二關(guān)... 玩家1進(jìn)入第二關(guān)... 玩家2進(jìn)入第二關(guān)... 玩家0進(jìn)入第二關(guān)...
CyclicBarrier和CountDownLatch的區(qū)別
- CountDownLatch: 一個(gè)線程(或者多個(gè)), 等待另外N個(gè)線程完成某個(gè)事情之后才能執(zhí)行。
- CyclicBarrier: N個(gè)線程相互等待,任何一個(gè)線程完成之前,所有的線程都必須等待。
- CountDownLatch的計(jì)數(shù)器只能使用一次。而CyclicBarrier的計(jì)數(shù)器可以使用reset() 方法重置。所以CyclicBarrier能處理更為復(fù)雜的業(yè)務(wù)場(chǎng)景,比如如果計(jì)算發(fā)生錯(cuò)誤,可以重置計(jì)數(shù)器,并讓線程們重新執(zhí)行一次。
- CountDownLatch:減計(jì)數(shù)方式,CyclicBarrier:加計(jì)數(shù)方式
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
Java設(shè)計(jì)模式之創(chuàng)建者模式詳解
這篇文章主要介紹了Java設(shè)計(jì)模式之創(chuàng)建者模式詳解,創(chuàng)建者模式,顧名思義,就是提供友好的創(chuàng)建對(duì)象的方式?,對(duì)象都是?new?出來(lái)的,但是在一些情況下,這種方式不是很友好,首先,它不夠直觀,需要的朋友可以參考下2023-08-08java實(shí)現(xiàn)的漢字轉(zhuǎn)五筆功能實(shí)例
這篇文章主要介紹了java實(shí)現(xiàn)的漢字轉(zhuǎn)五筆功能,結(jié)合具體實(shí)例形式分析了java基于字符串遍歷與編碼轉(zhuǎn)換等操作實(shí)現(xiàn)五筆編碼獲取的相關(guān)操作技巧,需要的朋友可以參考下2017-06-06深入理解JAVA基礎(chǔ)類庫(kù)中對(duì)象Object類
Object類是一個(gè)特殊的類,是所有類的父類,如果一個(gè)類沒(méi)有用extends明確指出繼承于某個(gè)類,那么它默認(rèn)繼承Object類。這里主要總結(jié)Object類中的兩個(gè):toString()與equals()方法2021-09-09Springboot下使用Redis管道(pipeline)進(jìn)行批量操作
本文主要介紹了Spring?boot?下使用Redis管道(pipeline)進(jìn)行批量操作,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05Servlet實(shí)現(xiàn)簡(jiǎn)單文件上傳功能
這篇文章主要為大家詳細(xì)介紹了Servlet實(shí)現(xiàn)簡(jiǎn)單文件上傳功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10Java中excel表數(shù)據(jù)的批量導(dǎo)入方法
這篇文章主要為大家詳細(xì)介紹了Java中excel表數(shù)據(jù)的批量導(dǎo)入方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05