Java多線程循環(huán)柵欄CyclicBarrier正確使用方法
前言
本篇文章的代碼示例已放到 github 上,Git地址為:advance(記錄每一個學習過程),大家把代碼下載下來之后,全局搜索一些關鍵代碼,即可找到該文章的源碼。
使用場景
想象一個這樣的場景,我們在打王者榮耀/英雄聯(lián)盟的時候,都會有一個匹配機制,需要10個人都加載完成后,大家才能一起進入游戲,不然會出現大家進入游戲的時間不一致的情況,這個時候就可以使用CyclicBarrier來實現。
基本原理
使用CyclicBarrier的線程被叫做參與方,它的內部維護了一個顯式鎖。參與方只需要執(zhí)行await()就可以參與等待,此時這些線程會被暫停。當最后一個線程執(zhí)行await()方法后,其他被暫停的線程都會被喚醒,而最后一個線程不會被暫停。
常用方法
//構造器,定義參與的線程數 CyclicBarrier cyclicBarrier = new CyclicBarrier(10); //構造器,可以傳入跳柵后需要執(zhí)行的線程 public CyclicBarrier(int parties, Runnable barrierAction); //將屏障重置為其初始狀態(tài) void reset() //進行等待 int await() //進行等待,同時具備超時時間 public int await(long timeout, TimeUnit unit)
使用示例
定義玩家運行程序
public class CyclicBarrierRunnable implements Runnable{
private CyclicBarrier cyclicBarrier;
private int number;
public CyclicBarrierRunnable(CyclicBarrier cyclicBarrier, int number) {
this.cyclicBarrier = cyclicBarrier;
this.number = number;
}
@Override
public void run() {
System.out.println("玩家" + number + "號正在加載游戲...");
try {
TimeUnit.SECONDS.sleep(2);
cyclicBarrier.await();
} catch (Exception e) {
System.out.println("線程執(zhí)行出現問題");
}
System.out.println("玩家" + number + "號加載完成。");
}
}定義主程序
public class Main {
public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
CyclicBarrier cyclicBarrier = new CyclicBarrier(10);
//獲取參與方的總數
System.out.println("參與方的總數為:" + cyclicBarrier.getParties());
//獲取此時等待的線程數
System.out.println("此時等待的線程數為:" + cyclicBarrier.getNumberWaiting());
for (int i = 0; i < 10; i++){
CyclicBarrierRunnable runnable = new CyclicBarrierRunnable(cyclicBarrier, i);
new Thread(runnable).start();
}
}
}運行結果

執(zhí)行說明
主線程每隔2秒會啟動一個子線程執(zhí)行,子線程打印“準備執(zhí)行”后,會調用await()方法進行等待,從結果我們可以看出:當最后一個CyclicBarrier.await()方法被執(zhí)行后,所有的等待線程同時被喚醒,同時開始執(zhí)行。
內部原理
CyclicBarrier內部使用了一個條件變量trip來實現等待/通知。
CyclicBarrier內部實現使用了分代的概念用于表示CyclicBarrier實例是可以重復使用的。
除最后一個線程外的任何一個參與方都相當于一個等待線程,這些線程所使用的保護條件是:“當前分代內,尚未執(zhí)行await方法的參與方個數為0”。await()方法每被執(zhí)行一次,相應實例的parties值會減少1.最后一個線程相當于通知線程,它執(zhí)行await()會使相應實例的parties的值變?yōu)?,此線程會先執(zhí)行barrierAction.run(),然后再執(zhí)行trip.signalAll()來喚醒所有等待線程。
注意事項
- 使用reset()方法將屏障置為初始狀態(tài)時,如果所有參與者目前都在屏障處等待,則將他們喚醒,同時拋出一個BrokenBarrierException異常
以上就是Java多線程循環(huán)柵欄CyclicBarrier正確使用方法的詳細內容,更多關于Java多線程循環(huán)柵欄CyclicBarrier的資料請關注腳本之家其它相關文章!
相關文章
Spring-Security對HTTP相應頭的安全支持方式
這篇文章主要介紹了Spring-Security對HTTP相應頭的安全支持方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10
Intellij IDEA 最全超實用快捷鍵整理(長期更新)
這篇文章主要介紹了Intellij IDEA 最全實用快捷鍵整理(長期更新),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02

