You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CountDownLatch await()未等待最后线程执行结束问题排查

问题根源

你对CountDownLatch的核心等待/通知机制理解没有偏差,输出不符合预期的核心原因是**countDown()的调用时机错误**:

  • 你的代码中,工作线程执行完Thread.sleep(5000)后,会先调用doneSignal.countDown(),再打印"Task ended by thread"日志
  • CountDownLatch的规则是:当内部计数减到0的瞬间,所有阻塞在await()方法的线程会立刻被唤醒执行,不会等待调用countDown()的线程执行完后续代码
  • 当第5个线程执行完countDown()时,doneSignal计数归0,主线程立刻从await()处返回,打印"All Tasks Completed";此时剩下几个还没来得及执行"Task ended"打印的工作线程会和主线程并行输出,就出现了完成提示早于部分任务结束日志的现象。
修复方法

调整performTask()方法内的执行顺序,确保线程所有自身任务逻辑(包括结束日志打印)全部执行完成后,再调用countDown()递减计数即可:

private void performTask() {
    try {
        System.out.println("Task started by thread : " + id);
        Thread.sleep(5000);
        // 先执行完所有任务收尾逻辑,再通知计数减一
        System.out.println("Task ended by thread : " + id);
        doneSignal.countDown();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

额外优化建议

当前写法如果任务执行过程中抛出未捕获异常,会导致countDown()无法被调用,最终主线程会永久阻塞在doneSignal.await()处。更稳妥的写法是将countDown()放到finally块中保证一定执行,示例:

@Override
public void run() {
    try {
        startSignal.await();
        performTask();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        doneSignal.countDown();
    }
}

private void performTask() throws InterruptedException {
    System.out.println("Task started by thread : " + id);
    Thread.sleep(5000);
    System.out.println("Task ended by thread : " + id);
}

调整后运行输出就会和你的预期完全一致。

内容的提问来源于stack exchange,提问作者kaddy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 10:57:54