Java面试题更新 2026-08-05

请解释 Java 中 wait、notify 与 notifyAll 方法的作用,包括它们的调用条件、行为差异以及典型使用场景。

风险判断技术原理Java

考察说明

考查对 Java 线程间通信机制中 wait、notify、notifyAll 的理解,包括使用前提、行为差异与注意事项。

回答思路

  1. 【回答框架 1】wait、notify、notifyAll 是 Object 类的方法,用于线程间协作。wait 使当前线程进入等待状态并释放监视器锁,调用前提是当前线程持有该对象的监视器锁(即处于 synchronized 块或方法中),否则抛出 IllegalMonitorStateException。
  2. 【回答框架 2】notify 随机唤醒一个正在该对象上等待的线程,而 notifyAll 唤醒所有等待线程。被唤醒的线程需重新竞争锁,且在 wait 返回后应重新检查条件,因为可能发生虚假唤醒(spurious wakeup)。
  3. 【回答框架 3】典型使用场景是生产者-消费者模型:生产者用 notify 或 notifyAll 通知消费者有数据可用,消费者在条件不满足时调用 wait 等待。正确写法是使用 while 循环包裹 wait,避免虚假唤醒和条件竞争。
  4. 【回答框架 4】wait 有超时版本 wait(long timeout),超时后自动苏醒。与 sleep 不同,wait 会释放锁,而 sleep 不释放锁。这些方法只能在同步上下文中调用,且锁对象需一致。
  5. 【关键点 1】调用 wait、notify、notifyAll 前必须持有对象监视器锁,否则抛 IllegalMonitorStateException。
  6. 【关键点 2】wait 释放锁并进入等待;notify 唤醒一个等待线程,notifyAll 唤醒所有等待线程。
  7. 【关键点 3】应使用 while 循环包裹 wait 条件,以应对虚假唤醒。
  8. 【关键点 4】notify 唤醒的线程仍需参与锁竞争,且不保证特定线程被唤醒。
  9. 【关键点 5】wait(long timeout) 可设置超时,超时后自动唤醒。
  10. 【易错点 1】在非同步代码块中调用 wait 或 notify 会抛出 IllegalMonitorStateException。
  11. 【易错点 2】只使用 notify 可能因唤醒特定线程导致死锁或未处理事件,需按场景选择 notifyAll。
  12. 【易错点 3】条件判断用 if 而非 while,可能因虚假唤醒导致条件不满足时继续执行。