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

调用join()时Thread的interrupt()为何不总是抛出InterruptedException?

问题:主线程调用join()时为何偶尔才抛出InterruptedException?

我编写了如下代码:

主类启动Worker线程:

public class Main {
    public static void main(String[] args) {
        var worker = new Worker(Thread.currentThread());
        worker.start();
        try {
            worker.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

Worker线程在run()方法中中断主线程:

public class Worker extends Thread {

    private final Thread master;
    public Worker(Thread master) {
        this.master = master;
    }

    @Override
    public void run() {
        master.interrupt();
    }
}

根据join()的文档说明,当当前线程被中断时会抛出InterruptedException,且中断状态会被清除。我预期主线程总会抛出该异常,但实际仅偶尔抛出。我查看join()方法发现它会先检查线程是否存活再调用wait(),这是否是异常不总是抛出的原因?


回答

你的猜测完全正确,核心原因就是join()方法的执行时序问题。

join()的核心逻辑大致是这样的:当主线程调用worker.join()时,会先检查Worker线程是否存活:

  1. 如果Worker线程已经执行完毕(也就是已经调用了master.interrupt()并终止),join()会直接返回,不会进入后续的wait()等待逻辑。此时主线程的中断状态确实被设置了,但join()没走到会响应中断的步骤,自然不会抛出InterruptedException。
  2. 如果Worker线程还存活,主线程会进入wait()状态等待Worker结束。这时候Worker线程执行master.interrupt(),会唤醒主线程的wait(),此时join()会检测到主线程的中断状态,抛出InterruptedException并清除中断标记。

简单说就是:

  • 当Worker线程跑得比主线程的join()存活检查快时,join()直接返回,不触发异常;
  • 当Worker线程跑得慢,主线程先进入wait(),此时中断会触发异常。

你可以做两个验证:

  • 在Worker的run()方法里加一行Thread.sleep(100),让它慢于主线程的join()调用,这样每次都会抛出异常;
  • 在主线程的join()之后加一行System.out.println(Thread.currentThread().isInterrupted()),会发现那些没抛出异常的情况里,主线程的中断状态是true。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 21:36:09