为何等待线程调用interrupt()有效,notify()却无法唤醒?
线程notify()唤醒失效原因解析
问题描述
创建了两个示例类(忽略Map的get(1L)访问细节,仅还原真实项目核心数据结构),核心问题为线程唤醒异常:
- MyThread类:创建匿名线程,该线程在自身监视器(
synchronized(this))上调用wait()进入等待;主线程调用该线程的join()等待其结束。 - Handler类:内部维护存储线程的Map,计数到3时,对目标线程同步后调用
t.notify(),但无法唤醒等待线程;替换为t.interrupt()则能成功中断并唤醒线程。
确认使用同一监视器,但notify()失效,寻求原因解析。
MyThread类代码
public class MyThread { public static void main(String[] args) { MyThread t = new MyThread(); } public MyThread() { Thread t = new Thread() { @Override public void run() { synchronized (this) { try { wait(); } catch (InterruptedException e) { System.out.println("interrupted"); } } } }; Handler handler = new Handler(t); System.out.println("starting thread"); t.start(); try { t.join(); System.out.println("joined! (woke up)"); } catch (InterruptedException e) { System.out.println("MyThread interrupted"); } } }
Handler类代码
public class Handler { NavigableMap<Long, Set<Thread>> map = new TreeMap<>(); public Handler(Thread t2) { System.out.println("in Handler"); map.put(1L, new HashSet<>()); map.get(1L).add(t2); Thread t = new Thread(new Runnable() { int counter = 0; @Override public void run() { try { while (true) { System.out.println("waiting: " + counter); Thread.sleep(3000); if (++counter == 3) { for (Thread t : map.get(1L)) { synchronized (t) { System.out.println("notifying!"); t.notify(); System.out.println("notified!"); } } } } } catch (InterruptedException e) { throw new RuntimeException(e); } } }); t.start(); } }
原因解析
问题核心是Thread类的join()方法会占用线程对象的监视器锁,并在内部调用wait(),和你自己的wait()调用产生了唤醒冲突。
具体执行流程:
- 匿名线程启动后,进入
run()方法,获取自身监视器锁,调用wait()释放锁并进入等待状态。 - 主线程调用
t.join(),join()的内部实现会先获取t的监视器锁,然后调用t.wait()(目的是等待线程终止)。 - Handler中的计数线程计数到3时,获取
t的监视器锁并调用t.notify(),但这个notify()唤醒的是主线程中因join()而进入等待的线程,而非匿名线程里调用wait()的那个等待状态。 - 主线程被唤醒后,会检查匿名线程是否已经终止(此时匿名线程还在
wait()状态,并未结束),所以主线程会再次调用t.wait(),重新进入等待。而匿名线程的wait()始终没被唤醒,导致程序卡住。
换成t.interrupt()时,会直接触发匿名线程的wait()抛出InterruptedException,让匿名线程退出等待并结束运行,主线程的join()检测到线程终止后自然完成,所以能成功“唤醒”整个流程。
简单总结:你的notify()被主线程的join()“截胡”了,唤醒的是主线程而非目标等待线程。
内容的提问来源于stack exchange,提问作者rzdrrw
相关产品推荐
相关产品推荐

