wait() 是 java 中构建阻塞队列的核心协作工具,需在 synchronized 块中调用,配合 while 循环防虚假唤醒、notify()/notifyall() 选择唤醒策略,并在释放锁后重新竞争锁以保证原子性。

在 Java 中,wait() 方法本身不直接实现阻塞队列,而是配合 synchronized 和 notify()/notifyAll() 构建线程间协作机制,是手动实现阻塞队列(如基于数组或链表的自定义队列)时控制线程阻塞与唤醒的核心工具。
wait() 必须在 synchronized 块中调用
调用 wait() 前必须持有对象锁,否则抛出 IllegalMonitorStateException。典型写法是将队列的锁对象(通常是 this 或专用锁对象)作为同步目标:
- 入队时若队满,需在同步块内调用
wait()暂停当前线程 - 出队时若队空,同样在同步块内调用
wait() - 每次
wait()后应使用 while 循环重新检查条件,防止虚假唤醒
用 while 循环包裹 wait() 防止虚假唤醒
wait() 返回不保证条件成立,可能因其他线程干扰或系统信号提前唤醒。因此不能用 if 判断,必须用 while:
while (queue.isEmpty()) {
wait();
}
出队操作中,只有队列非空才继续取元素;同理,入队前要 while 检查是否已满。
notify() 与 notifyAll() 的选择影响吞吐与公平性
当生产者插入元素后,需唤醒等待的消费者;消费者取走元素后,需唤醒等待的生产者:
-
notify()只唤醒一个等待线程,适合单生产者-单消费者场景,减少不必要的上下文切换 -
notifyAll()唤醒所有等待线程,由它们竞争锁并重新判断条件,更安全,适用于多生产者或多消费者场景 - 避免只用
notify()却未区分等待类型(如满等 vs 空等),否则可能唤醒错的线程导致死锁
wait() 释放锁,被唤醒后需重新竞争锁
调用 wait() 会立即释放当前持有的锁,并使线程进入 WAITING 状态;被 notify() 或 notifyAll() 唤醒后,线程进入锁竞争队列,只有重新获得锁才能继续执行后续逻辑。这意味着:
- 唤醒不等于立即执行,仍需等待锁可用
- 条件判断和操作必须在同一个同步块内完成,确保原子性
- 不能在
wait()外修改共享状态,否则破坏同步契约
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











