CyclicBarrier入門代碼解析

文章目錄

      • 核心思想:組隊出游,人到齊了才出發 🚌
      • 最簡單易懂的代碼示例
      • 代碼解析
      • 運行效果分析
      • `CyclicBarrier` vs `CountDownLatch` 的關鍵區別
      • CyclicBarrier在業務系統里面通常有什么常用的應用場景
      • 核心應用模式
      • 1. 數據并行處理與ETL(最經典)
      • 2. 模擬高并發測試
      • 3. 多線程數據計算與合并
      • 4. 游戲服務器中的多玩家同步
      • 總結

核心思想:組隊出游,人到齊了才出發 🚌

想象一下,您和幾個朋友約好一起去旅游。大家從各自的家里出發,約定在火車站門口集合。CyclicBarrier 就好比是這個“集合點”。

  • 規則:必須所有人都到達火車站門口后,大家才能一起進站上車。先到的人必須在門口等著,直到最后一個人到達。
  • CyclicBarrier barrier = new CyclicBarrier(3);
    • 這等于約定了這次出游的小隊有 3個人。這個 3 就是需要到達“柵欄”(Barrier)的線程數量。
  • barrier.await(); (等待)
    • 每個朋友(線程)到達火車站門口時,就調用一次這個方法。
    • 這個方法的意思是:“我到了,我開始等待其他人。” 然后這個線程就會被阻塞
  • 觸發開柵
    • 當第3個朋友(最后一個線程)也到達并調用 await() 時,“集結”條件達成!
    • 柵欄會“打開”,所有之前在 await() 處等待的線程會被同時喚醒,然后大家一起繼續執行后面的任務(比如進站)。
  • 循環使用 (Cyclic)
    • 最關鍵的是,這個柵欄是可以重復使用的。比如大家進站后,又可以約定在“檢票口”作為下一個集合點,再次使用同一個 CyclicBarrier 等待所有人檢票后一起上車。

最簡單易懂的代碼示例

下面我們就用代碼來模擬 3個朋友約定集合 的場景。我們還會用到 CyclicBarrier 的一個高級功能:當最后一個人到達時,可以指定一個額外的任務(比如由最后一個人高喊“人齊了,出發!”)。

import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class SimpleCyclicBarrierDemo {public static void main(String[] args) {// 1. 創建一個 CyclicBarrier//    參數1: 參與的線程數量(小隊人數為3)//    參數2: 當最后一個線程到達柵欄時,要執行的任務(可選)final int teamSize = 3;final CyclicBarrier barrier = new CyclicBarrier(teamSize, () -> {// 這個任務會由最后一個到達柵欄的線程來執行System.out.println("\n*** 所有人都到齊了!由我(最后到達者)來宣布:出發! ***\n");});// 創建一個線程池來管理我們的朋友線程ExecutorService executor = Executors.newFixedThreadPool(teamSize);System.out.println("--- 3個朋友各自從家里出發 ---");// 2. 模擬3個朋友出發for (int i = 0; i < teamSize; i++) {final String friendName = "朋友-" + (i + 1);executor.submit(() -> {try {// 模擬從家里到集合點的耗時int travelTime = new Random().nextInt(5000) + 1000; // 隨機1-6秒System.out.println("[" + friendName + "] 出發了,大概需要 " + travelTime / 1000 + " 秒...");Thread.sleep(travelTime);System.out.println(">>> [" + friendName + "] 到達集合點,開始等待其他人...");// 3. 關鍵!調用 await() 表示自己已到達,并開始等待//    線程會在這里被阻塞,直到所有3個線程都調用了 await()barrier.await();// --- 當所有人都到達后,線程會從 await() 返回,繼續執行 ---System.out.println("<<< [" + friendName + "] 跟隨大部隊一起出發!");} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}});}// 關閉線程池executor.shutdown();}
}

在這里插入圖片描述

代碼解析

  1. new CyclicBarrier(3, ...): 創建了一個需要3個線程“報到”的柵欄。同時還指定了一個“柵欄任務”,這個任務會在第3個線程報到時,由那個線程順便完成。
  2. barrier.await(): 這是每個線程的“報到點”。先到的線程會在這里停下(阻塞),耐心等待后到的同伴。
  3. barrierAction (第二個參數): 當最后一個(第3個)線程調用await()時,它不會立刻阻塞,而是先去執行這個我們預設好的任務(打印“所有人都到齊了…”),執行完之后,柵欄才會打開,所有線程(包括它自己)才能繼續前進。

運行效果分析

當你運行程序時,你會看到:

  1. 3個朋友會不按順序地、在不同時間點打印“到達集合點…”。
  2. 先到的1、2個朋友在打印完這句話后就不會有任何輸出了,因為它們被 await() 阻塞了。
  3. 直到最后一個朋友也打印了“到達集合點…”,并調用了 await() 后,你會立刻看到:
    a. 首先打印出 *** 所有人都到齊了!... *** 這條消息(由最后到達的線程執行)。
    b. 緊接著,3個線程會幾乎同時打印出 <<< [朋友-X] 跟隨大部隊一起出發! 的信息。

CyclicBarrier vs CountDownLatch 的關鍵區別

特性CyclicBarrier (循環柵欄)CountDownLatch (倒數門閂)
作用對象一組線程相互等待一個或多個線程等待其他線程
關系朋友之間,地位平等老板和員工,一個等多個
可重用性可循環使用。所有線程通過后,計數器重置,可用于下一輪集合。一次性。計數減到0后就失效了,無法重置。
功能功能更強大,可以附加一個barrierAction任務。功能相對簡單。

簡單總結CountDownLatch 是一個線程等其他所有線程完事,而 CyclicBarrier 是所有線程互相等,等齊了再一起干下一件事。

CyclicBarrier在業務系統里面通常有什么常用的應用場景

好的,這個問題非常好!從學習一個工具的API到理解它在真實業務系統中的價值,是成為一個優秀工程師的關鍵一步。

CyclicBarrier 的核心是“讓一組線程相互等待,直到所有線程都到達一個公共的屏障點,然后再一起繼續執行”。基于這個特性,它在業務系統中有幾個非常經典和常用的應用場景。


核心應用模式

所有場景都可以歸結為一個模式:將一個大任務拆分成多個獨立的子任務,讓多個線程并行處理,但在某些關鍵的“同步點”(屏障),這些線程必須等待彼此,直到所有線程都到達這個點,然后才能一起進入下一個階段。

下面是幾個具體的業務場景:

1. 數據并行處理與ETL(最經典)

這是 CyclicBarrier 最常見的用途,尤其是在大數據和數據倉庫領域。想象一下,你需要處理一個巨大的數據文件(例如,幾千萬條用戶數據),整個過程分為三個階段:

  1. 數據讀取(Read): 從文件中讀取數據到內存。
  2. 數據處理(Process): 對內存中的數據進行清洗、轉換、計算。
  3. 數據寫入(Write): 將處理好的數據寫入到數據庫。

為了提高效率,你可以啟動多個線程,每個線程負責處理文件的一部分。但這里的關鍵是,必須等所有線程都完成了上一個階段,才能一起開始下一個階段

  • 場景: 必須等所有線程都讀取完畢,數據才算完整,才能開始處理
  • 場景: 必須等所有線程都處理完畢,才能開始寫入,以保證數據的一致性。

CyclicBarrier 在這里的作用:
就像一個階段性的流水線

  • 創建一個 CyclicBarrier,參與方數量就是你的線程數。
  • 每個線程完成自己的數據讀取后,調用 barrier.await()
  • 當最后一個線程也完成讀取并調用await()后,所有線程被喚醒,一起進入數據處理階段。
  • 處理完后,再次調用 barrier.await(),等待所有同伴,然后一起進入數據寫入階段。
  • CyclicBarrier的“可循環使用”特性在這里得到了完美體現。
// 偽代碼
void processData() {// 階段1:讀取數據readMyChunk();barrier.await(); // 等待所有線程讀完// 階段2:處理數據processMyChunk();barrier.await(); // 等待所有線程處理完// 階段3:寫入數據writeMyChunk();
}

2. 模擬高并發測試

在做性能壓測時,我們常常需要模擬“在同一瞬間,有大量用戶請求同時到達服務器”的場景,以測試系統的瞬時承載能力。

如果只是簡單地用一個 for 循環啟動幾百個線程,那么這些線程的啟動時間會有先后,無法做到真正的“同時并發”。

CyclicBarrier 在這里的作用:
就像一個賽跑的起跑線

  1. 創建一個 CyclicBarrier,參與方數量就是并發用戶數(比如500)。
  2. 啟動500個線程,每個線程模擬一個用戶。
  3. 每個線程在真正發起HTTP請求之前,先執行各自的準備工作(比如準備參數、建立連接等)。
  4. 準備工作完成后,每個線程都調用 barrier.await()
  5. 此時,所有500個線程都會在“起跑線”上被阻塞,等待發令槍。
  6. 當最后一個(第500個)線程也準備好并調用await()時,柵欄打開,所有500個線程會幾乎在同一時刻被喚醒,然后同時向服務器發起請求,從而達到了模擬瞬時高并發的目的。

3. 多線程數據計算與合并

在科學計算或金融分析等領域,一個復雜的計算任務可以被分解。例如,計算一個大矩陣,可以把矩陣切成好幾塊,分給不同線程計算。

  • 場景:每個線程計算完自己的那一小塊后,需要用同伴們計算出的結果來計算下一輪的迭代值。
  • CyclicBarrier的作用:確保所有線程都完成了當前輪次的計算,并將結果保存在一個共享位置后,大家才能一起進入下一輪迭代。這保證了每一輪迭代的初始數據都是完整和同步的。

4. 游戲服務器中的多玩家同步

在網絡游戲中,CyclicBarrier 也非常有用。

  • 場景1:游戲開始前。一個游戲房間需要湊齊比如5個玩家才能開始。服務器可以為這個房間創建一個5個參與方的CyclicBarrier。每個玩家客戶端加載完地圖資源后,就向服務器報到(相當于調用await())。當第5個玩家也準備好后,服務器的柵欄打開,向所有5個客戶端同時發送“游戲開始”的指令。
  • 場景2:回合制游戲。在一回合結束后,需要等待所有玩家都確認“回合結束”,才能一起進入下一回合的準備階段。

總結

應用場景核心問題CyclicBarrier的作用
數據并行處理需要分階段、按步驟地處理數據,且每一階段都依賴上一階段的全部結果。作為階段同步點,確保所有線程同步進入下一階段。
高并發測試需要模擬大量線程在同一時刻觸發某個動作。作為起跑線,將所有線程“壓”在同一點,然后同時釋放。
并行算法算法需要多輪迭代,且每一輪的開始都依賴上一輪所有線程的計算結果。作為迭代同步點,確保所有線程同步進入下一輪迭代。
游戲同步需要等待所有參與者都達到某個狀態(如加載完成、回合結束)后才能繼續。作為玩家狀態同步點,確保游戲邏輯同步進行。

總而言之,當你遇到一個需要多個對等的線程相互協作,步調一致地完成一個分階段任務時,CyclicBarrier 就是一個非常理想的選擇。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/84833.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/84833.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/84833.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Maven 配置中繞過 HTTP 阻斷機制的完整解決方案

Maven 配置中繞過 HTTP 阻斷機制的完整解決方案 一、背景與問題分析 自 Maven 3.8.1 版本起&#xff0c;出于安全考慮&#xff0c;默認禁止了對 HTTP 倉庫的訪問。這一機制通過 <mirror> 配置中的 maven-default-http-blocker 實現&#xff0c;其作用是攔截所有使用 HT…

【大廠機試題解法筆記】恢復數字序列

題目 對于一個連續正整數組成的序列&#xff0c;可以將其拼接成一個字符串&#xff0c;再將字符串里的部分字符打亂順序。如序列8 9 10 11 12,拼接成的字符串為89101112,打亂一部分字符后得到90811211,原來的正整數10就被拆成了0和1。 現給定一個按如上規則得到的打亂字符的字…

MongoDB 事務有哪些限制和注意事項?

MongoDB 的多文檔 ACID 事務雖然強大&#xff0c;但在使用時確實有一些限制和需要特別注意的事項。 以下是主要的限制和注意事項&#xff1a; 1. 性能開銷 (Performance Overhead) 額外協調: 事務需要額外的協調工作&#xff0c;包括跟蹤事務狀態、管理鎖&#xff08;即使是樂…

CTF實戰技巧:獲取初始權限后如何高效查找Flag

CTF實戰技巧&#xff1a;獲取初始權限后如何高效查找Flag 在CTF比賽中&#xff0c;獲得初始訪問權限只是開始&#xff0c;真正的挑戰在于如何在系統中高效定位Flag。本文將分享我在滲透測試中總結的系統化Flag搜索方法&#xff0c;涵蓋Linux和Windows雙平臺。 引言&#xff1a;…

kafka Tool (Offset Explorer)使用SASL Plaintext進行身份驗證

一、前面和不需要認證的情況相同&#xff1a; 1、填寫Properties中的cluster name和版本&#xff0c;以及zk的ip和port 2、Advanced中填寫bootstrap servers 二、和不需要認證時不同的點&#xff1a; 1、Security的Type&#xff0c;不需要認證時選plaintext&#xff0c;需要認…

最小費用最大流算法

最小費用最大流算法 原理 問題:網絡中有源點(起點)和匯點(終點),每條邊有流量上限和單位流量費用。求: 從源點到匯點的最大流量在流量最大的前提下,總費用最小核心思想:在找增廣路時,選擇單位費用之和最小的路徑(使用SPFA找最短路) 實現步驟 建圖:使用鏈式前向…

從匯編的角度揭開C++ this指針的神秘面紗(上)

C中的this指針一直比較神秘。任何類的對象&#xff0c;都有一個this指針&#xff0c;無處不在。那么this指針的本質究竟是什么&#xff1f;this指針什么時候會被用到&#xff1f;今天通過幾段簡單的代碼&#xff0c;來揭秘一下。 要先揭秘this指針&#xff0c;先來說一下函數調…

18 - GCNet

論文《GCNet: Non-local Networks Meet Squeeze-Excitation Networks and Beyond》 1、作用 GCNet通過聚合每個查詢位置的全局上下文信息來捕獲長距離依賴關系&#xff0c;從而改善了圖像/視頻分類、對象檢測和分割等一系列識別任務的性能。非局部網絡&#xff08;NLNet&…

人工智能學習17-Pandas-查看數據

人工智能學習概述—快手視頻 人工智能學習17-Pandas-查看數據—快手視頻

RV1126+OPENCV在視頻中添加LOGO圖像

一.RV1126OPENCV在視頻中添加LOGO圖像大體流程圖 主要是利用RV1126的視頻流結合OPENCV的API在視頻流里面添加LOGO圖像&#xff0c;換言之就是在RV1126的視頻流里面疊加圖片。大體流程我們來看上圖&#xff0c;要完成這個功能我們需要創建兩個線程(實際上還有初始化過程&#xf…

汽車制造通信革新:網關模塊讓EtherCAT成功對接CCLINK

?在現代工業自動化生產領域&#xff0c;不同品牌和類型的設備往往采用不同的通信協議&#xff0c;這給設備之間的互聯互通帶來了挑戰。某汽車制造企業的生產線上&#xff0c;采用了三菱FX5U PLC作為主站進行整體生產流程的控制和調度&#xff0c;同時配備了庫卡機器人作為從站…

vue父類跳轉到子類帶參數,跳轉完成后去掉參數

當通過路由導航的時候&#xff0c;由于父類頁面帶參數到子類&#xff0c;導致路徑上面有參數 這樣不僅不美觀&#xff0c;而且在點擊導航菜單按鈕時還會有各種問題&#xff0c;這時我們只需要將路由后面的參數去掉就好了&#xff0c;在子頁面mounted()函數里面獲取到父類的參數…

純 CSS 實現的的3種掃光效果

介紹一個比較常見的動畫效果。 在日常開發中&#xff0c;為了強調凸顯某些文本或者元素&#xff0c;會加一些掃光動效&#xff0c;起到吸引眼球的效果&#xff0c;比如文本的 或者是一個卡片容器&#xff0c;里面可能是圖片或者文本或者任意元素 除此之外&#xff0c;還有那…

如何在FastAPI中構建一個既安全又靈活的多層級權限系統?

title: 如何在FastAPI中構建一個既安全又靈活的多層級權限系統? date: 2025/06/14 12:43:05 updated: 2025/06/14 12:43:05 author: cmdragon excerpt: FastAPI通過依賴注入系統和OAuth2、JWT等安全方案,支持構建多層級權限系統。系統設計包括基于角色的訪問控制、細粒度權…

大模型_Ubuntu24.04安裝RagFlow_使用hyper-v虛擬機_超級詳細--人工智能工作筆記0251

因為之前使用dify搭建了一個知識庫&#xff0c;但是dify的效果&#xff0c;尤其是在文檔解析方面是非常不友好的&#xff0c;雖然測試了&#xff0c;納米的效果非常好&#xff0c;但是納米只能容納2000個文件&#xff0c;如果 你的知識庫中有代碼&#xff0c;sql文件等等&…

LeetCode - LCR 173. 點名

題目 LCR 173. 點名 - 力扣&#xff08;LeetCode&#xff09; 思路 首先對數組進行排序&#xff0c;使學號按順序排列 在排序后的數組中&#xff0c;如果沒有缺失的學號&#xff0c;那么每個元素應該等于其索引值 使用二分查找找到第一個不等于其索引的元素位置&#xff1…

VSCode如何優雅的debug python文件,包括外部命令uv run main.py等等

debug程序的方式有很多種。每一種方式都各有缺點:有的方式雖然優雅,但是局限性很大;有的方式麻煩,但是局限性小。 常規方式: 優點:然后可以觀察所有線程。一勞永逸。缺點:就是寫參數很麻煩,但是你可以讓chatgpt等大模型幫你寫。最最最優雅的方式: 優點:就是需要在代碼…

[調試技巧]VS Code如何在代理模式下使用 MCP 工具?

在開發環境調試MCP&#xff0c;通過agent模式與大模型對話&#xff0c;并不能保證每次均正確調用tool。在閱讀官方文檔之后&#xff0c;得知以下小技巧。 添加 MCP 服務器后&#xff0c;您可以在代理模式下使用它提供的工具。要在代理模式下使用 MCP 工具 打開聊天視圖 (CtrlAl…

京東零售基于Flink的推薦系統智能數據體系 |Flink Forward Asia 峰會實錄分享

京東推薦系統的數據體系極其復雜&#xff0c;從召回、模型到策略和效果評估&#xff0c;每個環節都需要強大的海量數據處理能力支撐。然而&#xff0c;在實際運行中&#xff0c;整個數據鏈路面臨著諸多挑戰&#xff1a;如實時與離線數據的埋點口徑不一致、數倉模型存在偏差、計…

[學習] 牛頓迭代法:從數學原理到實戰

牛頓迭代法&#xff1a;從數學原理到實戰 ——高效求解方程根的數值方法 文章目錄 牛頓迭代法&#xff1a;從數學原理到實戰一、引言&#xff1a;為什么需要牛頓迭代法&#xff1f;二、數學原理&#xff1a;幾何直觀與公式推導1. **核心思想**2. **幾何解釋**3. **收斂性分析*…