什么是 Java 的 CyclicBarrier(代碼示例)
你的回答(口語化,面試場景)
面試官:什么是 Java 的 CyclicBarrier?
你:
好的,我來舉個例子說明。比如一個游戲需要5個玩家全部準(zhǔn)備就緒才能開始,這時候可以用 CyclicBarrier。
核心作用CyclicBarrier 讓一組線程互相等待,直到所有線程都到達(dá)屏障點(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é)點完成初始化后,同時對外提供服務(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 底層是如何實現(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)用
知識框架與底層原理補充
核心機制
| 組件 | 作用 |
|---------------------|-------------------------------------------------------------------------|
| 屏障點(Barrier) | 線程必須等待其他線程到達(dá)的位置。 |
| Generation | 記錄當(dāng)前屏障的狀態(tài)(是否已破壞),支持重置后復(fù)用。 |
| 回調(diào)任務(wù) | 可選的 Runnable,由最后一個到達(dá)屏障的線程執(zhí)行。 |
源碼級實現(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)入等待隊列。
實戰(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ù))。
- 理解底層鎖機制和異常處理,避免因線程中斷導(dǎo)致屏障失效。
- 優(yōu)先于 CountDownLatch 的場景:需重復(fù)觸發(fā)同步點,或需要回調(diào)任務(wù)統(tǒng)一處理結(jié)果。
到此這篇關(guān)于什么是 Java 的 CyclicBarrier的文章就介紹到這了,更多相關(guān)Java 的 CyclicBarrier內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java泛型模擬scala實現(xiàn)自定義ArrayList方式
這篇文章主要介紹了Java泛型模擬scala實現(xiàn)自定義ArrayList方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10
踩坑之spring事務(wù),非事務(wù)方法與事務(wù)方法執(zhí)行相互調(diào)用方式
這篇文章主要介紹了踩坑之spring事務(wù),非事務(wù)方法與事務(wù)方法執(zhí)行相互調(diào)用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
詳細(xì)聊聊Spring MVC重定向與轉(zhuǎn)發(fā)
大家應(yīng)該都知道請求重定向和請求轉(zhuǎn)發(fā)都是web開發(fā)中資源跳轉(zhuǎn)的方式,這篇文章主要給大家介紹了關(guān)于Spring MVC重定向與轉(zhuǎn)發(fā)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-09-09

