什么是 Java 的 CyclicBarrier(代碼示例)
你的回答(口語化,面試場景)
面試官:什么是 Java 的 CyclicBarrier
?
你:
好的,我來舉個例子說明。比如一個游戲需要5個玩家全部準(zhǔn)備就緒才能開始,這時候可以用 CyclicBarrier
。
核心作用CyclicBarrier
讓一組線程互相等待,直到所有線程都到達(dá)屏障點(diǎn)(Barrier),再一起繼續(xù)執(zhí)行。它像一道關(guān)卡,必須等所有線程到齊才能放行。
核心特性
- 可重復(fù)使用:所有線程通過屏障后,
CyclicBarrier
會自動重置(比如玩家結(jié)束一局后,可以開始下一局)。 - 支持回調(diào):可以設(shè)置一個回調(diào)任務(wù)(Runnable),在所有線程到達(dá)屏障后觸發(fā)(比如發(fā)游戲開始的廣播)。
- 使用場景
- 分階段任務(wù):多線程分批次處理數(shù)據(jù),等待所有線程完成第一階段后,再統(tǒng)一進(jìn)入第二階段。
- 壓測模擬:模擬1000個用戶同時發(fā)起請求(等所有線程就緒后同時觸發(fā))。
- 分布式協(xié)同:多個微服務(wù)節(jié)點(diǎn)完成初始化后,同時對外提供服務(wù)。
代碼示例
// 3個線程互相等待,全部到達(dá)后執(zhí)行回調(diào) CyclicBarrier barrier = new CyclicBarrier(3, () -> { System.out.println("所有玩家已就位,游戲開始!"); }); // 玩家線程 executor.submit(() -> { System.out.println("玩家A準(zhǔn)備完成"); barrier.await(); // 等待其他玩家 System.out.println("玩家A開始游戲"); }); // 類似地提交玩家B、C的線程
對比 CountDownLatch
- 重置能力:
CyclicBarrier
可重復(fù)用,CountDownLatch
只能一次性。 - 觸發(fā)角色:
CyclicBarrier
是線程互相等待,CountDownLatch
是主線程等待子線程。
預(yù)測面試官可能的追問及回答
追問1:如果某個線程在 await()
時被中斷了,會發(fā)生什么?
回答:
- 被中斷的線程會拋出
InterruptedException
,同時其他等待的線程會收到BrokenBarrierException
,屏障會失效。 - 需要調(diào)用
reset()
重置屏障后才能繼續(xù)使用。
追問2:CyclicBarrier
底層是如何實(shí)現(xiàn)的?
回答:
- 基于
ReentrantLock
和Condition
。- 內(nèi)部維護(hù)一個計數(shù)器,線程調(diào)用
await()
時計數(shù)器減1。 - 當(dāng)計數(shù)器歸零時,觸發(fā)回調(diào)任務(wù),并喚醒所有等待線程。
- 內(nèi)部維護(hù)一個計數(shù)器,線程調(diào)用
知識框架與底層原理補(bǔ)充
核心機(jī)制
| 組件 | 作用 |
|---------------------|-------------------------------------------------------------------------|
| 屏障點(diǎn)(Barrier) | 線程必須等待其他線程到達(dá)的位置。 |
| Generation | 記錄當(dāng)前屏障的狀態(tài)(是否已破壞),支持重置后復(fù)用。 |
| 回調(diào)任務(wù) | 可選的 Runnable
,由最后一個到達(dá)屏障的線程執(zhí)行。 |
源碼級實(shí)現(xiàn)邏輯
初始化:設(shè)置參與線程數(shù)(parties
)和回調(diào)任務(wù)。
await() 流程:
- 獲取鎖(
ReentrantLock
),檢查屏障是否已破壞(Broken
)。 - 減少剩余計數(shù)(
count
),若count == 0
,執(zhí)行回調(diào)并喚醒所有線程。 - 若未歸零,線程通過
Condition.await()
進(jìn)入等待隊列。
使用注意事項
- 獲取鎖(
ReentrantLock
),檢查屏障是否已破壞(Broken
)。 - 減少剩余計數(shù)(
count
),若count == 0
,執(zhí)行回調(diào)并喚醒所有線程。 - 若未歸零,線程通過
Condition.await()
進(jìn)入等待隊列。
實(shí)戰(zhàn)案例
- 場景:電商大促時,統(tǒng)計各區(qū)域銷量并匯總。
- 方案:
創(chuàng)建 CyclicBarrier
,線程數(shù)與區(qū)域數(shù)相同。
每個線程計算一個區(qū)域的銷量,完成后調(diào)用 await()
。
所有線程到達(dá)后,觸發(fā)回調(diào)任務(wù)匯總總銷量。
CyclicBarrier barrier = new CyclicBarrier(4, () -> { System.out.println("全部區(qū)域銷量計算完成,總銷量:" + total); }); // 4個區(qū)域計算線程 for (int i = 0; i < 4; i++) { executor.submit(() -> { calculateRegionSales(); barrier.await(); }); }
總結(jié)
- CyclicBarrier 是多線程協(xié)同的利器,適合需要多次同步的場景(如分階段任務(wù))。
- 理解底層鎖機(jī)制和異常處理,避免因線程中斷導(dǎo)致屏障失效。
- 優(yōu)先于 CountDownLatch 的場景:需重復(fù)觸發(fā)同步點(diǎn),或需要回調(diào)任務(wù)統(tǒng)一處理結(jié)果。
到此這篇關(guān)于什么是 Java 的 CyclicBarrier的文章就介紹到這了,更多相關(guān)Java 的 CyclicBarrier內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MyBatis的一級緩存和二級緩存以及優(yōu)點(diǎn)說明
MyBatis的緩存機(jī)制包括一級緩存和二級緩存,一級緩存是SqlSession級別的緩存,開啟默認(rèn),二級緩存是跨SqlSession的緩存,需要手動開啟和配置,二級緩存的優(yōu)點(diǎn)是減少數(shù)據(jù)庫訪問、提高性能、降低負(fù)載和提高可擴(kuò)展性,同時需要注意緩存可能導(dǎo)致的數(shù)據(jù)不一致問題2025-02-02基于Springboot+Vue實(shí)現(xiàn)的在線答題闖關(guān)系統(tǒng)全過程
這篇文章主要介紹了基于Springboot+Vue實(shí)現(xiàn)的在線答題闖關(guān)系統(tǒng)的相關(guān)資料,文中包括前端Vue.js、后端SpringBoot及MySQL數(shù)據(jù)庫的使用,系統(tǒng)功能涵蓋順序出題、體型練習(xí)、隨機(jī)出題、錯題本、收藏題和答題統(tǒng)計等,需要的朋友可以參考下2024-12-12java使用泛型實(shí)現(xiàn)棧結(jié)構(gòu)示例分享
泛型是Java SE5.0的重要特性,使用泛型編程可以使代碼獲得最大的重用。由于在使用泛型時要指明泛型的具體類型,這樣就避免了類型轉(zhuǎn)換。本實(shí)例將使用泛型來實(shí)現(xiàn)一個棧結(jié)構(gòu),并對其進(jìn)行測試2014-03-03Spring Security實(shí)現(xiàn)5次密碼錯誤觸發(fā)賬號自動鎖定功能
在現(xiàn)代互聯(lián)網(wǎng)應(yīng)用中,賬號安全是重中之重,然而,暴力 破解攻擊依然是最常見的安全威脅之一,攻擊者通過自動化腳本嘗試大量的用戶名和密碼組合,試圖找到漏洞進(jìn)入系統(tǒng),所以為了解決這一問題,賬號鎖定機(jī)制被廣泛應(yīng)用,本文介紹了Spring Security實(shí)現(xiàn)5次密碼錯誤觸發(fā)賬號鎖定功能2024-12-12Java實(shí)現(xiàn)學(xué)生信息管理界面
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)學(xué)生信息管理界面,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-06-06