【多线程】工具类
Phase:https://cloud.tencent.com/developer/article/1350849
CyclicBarrier
参考:https://blog.csdn.net/qq_38293564/java/article/details/80558157
栅栏类似于闭锁,它能阻塞一组线程直到某个事件的发生。
CyclicBarrier可以使一定数量的线程反复地在栅栏位置处汇集。当线程到达栅栏位置时将调用await方法,这个方法将阻塞直到所有线程都到达栅栏位置。如果所有线程都到达栅栏位置,那么栅栏将打开,此时所有的线程都将被释放,而栅栏将被重置以便下次使用。
CyclicBarrier构造方法
CyclicBarrier(int parties):其参数表示屏障拦截的线程数量,每个线程使用await()方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。
CyclicBarrier(int parties, Runnable barrierAction):用于线程到达屏障时,优先执行barrierAction,方便处理更复杂的业务场景
await方法:
public int await():用来挂起当前线程,直至所有线程都到达 barrier 状态再同时执行后续任务;
public int await(long timeout, TimeUnit unit):让这些线程等待至一定的时间,如果还有线程没有到达 barrier 状态就直接让到达 barrier 的线程执行后续任务。
public class CyclicBarrierTest { // 自定义工作线程 private static class Worker extends Thread { private CyclicBarrier cyclicBarrier; public Worker(CyclicBarrier cyclicBarrier) { this.cyclicBarrier = cyclicBarrier; } @Override public void run() { super.run(); try { System.out.println(Thread.currentThread().getName() + "开始等待其他线程"); cyclicBarrier.await(); System.out.println(Thread.currentThread().getName() + "开始执行"); // 工作线程开始处理,这里用Thread.sleep()来模拟业务处理 Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "执行完毕"); } catch (Exception e) { e.printStackTrace(); } } } public static void main(String[] args) { int threadCount = 3; CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount); for (int i = 0; i < threadCount; i++) { System.out.println("创建工作线程" + i); Worker worker = new Worker(cyclicBarrier); worker.start(); } } }
执行结果:
创建工作线程0 创建工作线程1 Thread-0开始等待其他线程 创建工作线程2 Thread-1开始等待其他线程 Thread-2开始等待其他线程 Thread-2开始执行 Thread-0开始执行 Thread-1开始执行 Thread-1执行完毕 Thread-0执行完毕 Thread-2执行完毕
CyclicBarrier和CountDownLatch的区别
CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset()方法重置,可以使用多次,所以CyclicBarrier能够处理更为复杂的场景;
CyclicBarrier还提供了一些其他有用的方法,比如getNumberWaiting()方法可以获得CyclicBarrier阻塞的线程数量,isBroken()方法用来了解阻塞的线程是否被中断;
CountDownLatch允许一个或多个线程等待一组事件的产生,而CyclicBarrier用于等待其他线程运行到栅栏位置。
CyclicBarrier vs CountdownLatch:CyclicBarrier可以通过reset()实现重置门限值,CountDownLatch为一次性。
CountDownLatch
注意:new CountDownLatch(5)中数字必须严格跟期望等待数字保持一致,否则可能出现意外的结果(因为超出5的线程会不被进行等待)
1、代码使用样例
通过CountDownLatch实现:"主线程"等待"5个子线程"全部都完成"指定的工作(休眠1000ms)"之后,再继续运行。

import java.util.concurrent.CountDownLatch; public class CountDownLatchTest { private static CountDownLatch latch = new CountDownLatch(5); public static void main(String[] args) { System.out.println("Main Thread start...."); System.out.println(); for (int i = 0; i < 5; i++) { new InnerThread().start(); } try { latch.await(); System.out.println(); System.out.println("Main Thread latch.getCount = " + latch.getCount()); } catch (InterruptedException e) { System.out.println("Exception happened in latch await: " + e); } System.out.println("Main Thread end...."); } static class InnerThread extends Thread { public void run() { synchronized (InnerThread.class) { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + " sleep 1000 ms."); // 将CountDownLatch的数值减1 latch.countDown(); System.out.println(Thread.currentThread().getName() + " count number: " + latch.getCount()); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
执行结果: 主线程等待,直至 latch 通过 countDown 减为0后,主线程才继续执行。

Main Thread start.... Thread-1 sleep 1000 ms. Thread-1 count number: 4 Thread-4 sleep 1000 ms. Thread-4 count number: 3 Thread-0 sleep 1000 ms. Thread-0 count number: 2 Thread-3 sleep 1000 ms. Thread-3 count number: 1 Thread-2 sleep 1000 ms. Thread-2 count number: 0 Main Thread latch.getCount = 0 Main Thread end....
2、常用方法解读
CountDownLatch(int count) // 构造一个用给定计数初始化的 CountDownLatch。 // 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。 void await() // 调用sync.acquireSharedInterruptibly(1)实现AQS中state=1 // 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。 boolean await(long timeout, TimeUnit unit) // 递减锁存器的计数,如果计数到达零,则释放所有等待的线程。 void countDown() // 调用sync.releaseShared(1) 实现AQS中state-1 long getCount() // 返回当前计数。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)