真实模拟高并发的关键是让所有线程在同一时刻触发请求,countdownlatch适用于一次性齐发压测,cyclicbarrier适用于多轮可复用的分阶段并发测试。

要在 Java 多线程并发测试中真实模拟高并发,关键不是“多开线程”,而是让所有线程**在同一时刻触发请求**。否则线程启动有毫秒级延迟,测出来的其实是串行或弱并发,容易误判系统吞吐能力。CountDownLatch 和 CyclicBarrier 正是解决这个问题的两个核心工具,但用法和适用场景不同。
CountDownLatch:适合“齐发式”压测
它像一把统一的“发令枪”——主线程等待所有工作线程就位,一声令下,全部同时发起请求。
- 初始化时传入线程总数,例如 new CountDownLatch(100)
- 每个工作线程启动后,先执行准备动作(如构造请求参数、建立连接),然后调用 latch.await() 阻塞等待
- 主线程在所有线程启动后,调用一次 latch.countDown(),瞬间唤醒全部线程
- 被唤醒的线程立即执行 HTTP 请求或业务逻辑,实现真正意义上的并发起点一致
注意:countDown() 只能调用一次,且必须由主线程(或唯一协调者)触发;若在工作线程里误调 countDown(),会导致部分线程提前释放,破坏同步效果。
CyclicBarrier:适合“分阶段+可复用”的并发循环测试
它更像一场接力赛的“检查点”——所有线程跑到同一位置才继续,且能反复使用,适合持续压测或分批次并发。
- 初始化时指定参与线程数,例如 new CyclicBarrier(100)
- 每个线程执行到关键点(如请求前)就调用 barrier.await(),自动阻塞直到凑齐 100 个
- 一旦满员,所有线程同时释放,一起发起请求;屏障随即重置,可再次 await
- 支持传入 barrierAction(一个 Runnable),在每次满员释放前执行,比如记录当前批次耗时、打印统计
优势在于:不用额外管理主线程协调逻辑,线程自己“等齐再动”,天然支持多轮并发(比如连续 5 轮每轮 100 并发),也便于做阶段性性能采样。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
别踩这两个坑
一是混用工具:想“齐发”却用了 CyclicBarrier 却没配 barrierAction,结果只测了单轮,没体现持续压力;想“多轮压测”却硬用 CountDownLatch,每轮都得重建实例,代码冗余还易出错。
- CountDownLatch 是“一次性门闩”,计数归零即失效,不可 reset(强行 new 新实例会丢失语义一致性)
- CyclicBarrier 可被中断或打破(比如某个线程超时退出),此时其他线程会抛 BrokenBarrierException,需捕获并处理,否则整轮测试中断
二是忽略资源清理:大量线程短时密集创建,务必用线程池(如 Executors.newFixedThreadPool(n))管控数量,避免 OOM 或系统线程耗尽;测试结束后记得 shutdown()。
一个极简对比示例
假设要发起 50 个并发请求:
- 用 CountDownLatch:主线程启动 50 个线程 → 每个线程 latch.await() → 主线程 latch.countDown() → 全部请求发出
- 用 CyclicBarrier:启动 50 个线程 → 每个线程执行到 barrier.await() → 自动齐发 → 完成后 barrier 可立即用于下一轮
选哪个,取决于你测的是“瞬时峰值”(选 CountDownLatch),还是“持续并发能力”(选 CyclicBarrier)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










