调用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线程是否存活:
- 如果Worker线程已经执行完毕(也就是已经调用了
master.interrupt()并终止),join()会直接返回,不会进入后续的wait()等待逻辑。此时主线程的中断状态确实被设置了,但join()没走到会响应中断的步骤,自然不会抛出InterruptedException。 - 如果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
相关产品推荐
相关产品推荐

