You need to enable JavaScript to run this app. 如何实现所有调用blockUntilCall的线程阻塞至doOnce被调用的机制?
优惠活动
大模型
产品
解决方案
定价
更多

如何实现所有调用blockUntilCall的线程阻塞至doOnce被调用的机制?

适配需求的最优实现

这个场景完全匹配JDK中CountDownLatch的设计目标,不需要手写锁逻辑,从根源上规避并发实现的常见坑。

核心实现逻辑

  • 初始化计数为1的CountDownLatch,代表触发事件仅需发生1次
  • blockUntilCall() 调用 await() 进入阻塞状态,直到 latch 计数归0
  • doOnce() 调用 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.23 02:15:04