如何实现所有调用blockUntilCall的线程阻塞至doOnce被调用的机制?
适配需求的最优实现
这个场景完全匹配JDK中CountDownLatch的设计目标,不需要手写锁逻辑,从根源上规避并发实现的常见坑。
核心实现逻辑
- 初始化计数为1的
CountDownLatch,代表触发事件仅需发生1次 blockUntilCall()调用await()进入阻塞状态,直到 latch 计数归0doOnce()调用countDown()将计数归0,一次性唤醒所有阻塞在await()上的线程
改造后的完整代码
import java.util.concurrent.CountDownLatch; public static class BlockMethodtillAnotherCalled { // 初始化计数为1,保证一次触发即可放行所有等待线程 private final CountDownLatch triggerSignal = new CountDownLatch(1); public void doOnce() { // 计数归0,唤醒所有等待的线程 triggerSignal.countDown(); } public void blockUntilCall() { try { System.out.println(Thread.currentThread().getName() + "现在被阻塞"); // 阻塞直到触发信号到达 triggerSignal.await(); System.out.println(Thread.currentThread().getName() + "现在已被释放"); } catch (InterruptedException e) { // 规范处理中断:恢复线程中断标记,交给上层逻辑处理 Thread.currentThread().interrupt(); } } }
关键特性说明
- 自动兼容时序竞态:如果某个线程在
doOnce()执行之后才调用blockUntilCall(),因为latch计数已经归0,await()会直接返回,不会出现永久阻塞的问题 - 幂等安全:
doOnce()被多次调用不会产生副作用,计数归0后重复调用不会改变状态 - 避免手写wait/notifyAll实现:原生等待通知机制很容易出现「线程刚准备进入wait状态时,触发方法已经执行完notifyAll」的时间窗口,导致线程永久阻塞。需要额外维护触发标记、双重检查锁等逻辑,代码复杂度高还容易出bug
内容的提问来源于stack exchange,提问作者Tony
相关产品推荐
相关产品推荐

