java中wait、notify、notifyall必须在synchronized块中调用,wait释放锁并进入等待队列,notify/notifyall不释放锁仅唤醒线程;需用while循环检查条件防虚假唤醒;优先选notifyall,中断时须正确处理interruptedexception。

Java 中 wait、notify 和 notifyAll 是 Object 类提供的原生线程协作机制,用于在共享对象上实现线程等待与唤醒。它们必须在 synchronized 块或方法中调用,否则会抛出 IllegalMonitorStateException。核心逻辑是:线程持有对象锁后,才能调用这些方法;调用 wait() 会释放锁并进入等待队列,直到被其他线程唤醒。
必须在 synchronized 上下文中使用
这三个方法操作的是对象的“等待队列(wait set)”,而只有获得该对象监视器(monitor)的线程才有权限操作它。因此:
- 调用前必须已通过
synchronized(obj)或synchronized实例/静态方法获取锁 -
wait()会立即释放锁,并让当前线程阻塞在该对象的等待队列中 -
notify()和notifyAll()不释放锁,只唤醒等待队列中的一个或全部线程(被唤醒线程需重新竞争锁)
用 while 循环检查条件,避免虚假唤醒
被 notify() 唤醒的线程不一定满足继续执行的条件(比如条件已被其他线程修改),所以不能用 if 判断后直接执行逻辑,必须用 while 循环重检条件:
synchronized (lock) {
while (!conditionMet) {
lock.wait(); // 等待条件成立
}
// 条件成立,安全执行后续操作
}
这是标准实践,也是 Object.wait() Javadoc 明确推荐的方式。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
notify 和 notifyAll 的选择要结合场景
notify() 只唤醒一个等待线程(具体哪个由 JVM 决定),适合“单生产者-单消费者”或条件唯一、唤醒一个即够的场景;notifyAll() 唤醒所有等待线程,适用于:
- 多个不同条件共用同一把锁(如生产者和消费者都 wait 在同一个 lock 上)
- 无法确保唤醒的线程恰好满足其所需条件
- 避免因唤醒错线程导致死锁或永久等待
实践中,除非能严格保证唤醒一个就足够且安全,否则优先用 notifyAll() 更稳妥。
注意中断与异常处理
wait() 可能被中断(抛出 InterruptedException),需正确捕获并响应中断(如恢复中断状态或退出):
try {
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复中断标志
return; // 或抛出 RuntimeException,取决于业务逻辑
}
不要忽略该异常,也不要简单吞掉——这会导致线程无法响应外部中断请求,影响程序可控性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










