object类不直接实现生产者-消费者模型,但其wait()/notify()/notifyall()方法提供底层线程协作能力,需在synchronized块中调用并配合while循环防止虚假唤醒,适用于学习原理或极简场景。

Object 类本身不直接实现生产者-消费者模型,但它的 wait()/notify()/notifyAll() 方法是 Java 中最基础的线程协作原语,为该模型提供了底层同步能力。关键在于:这些方法必须在 synchronized 代码块或方法中调用,且操作的是同一个对象的监视器(monitor)。
wait/notify 的基本协作逻辑
生产者和消费者通过共享对象(如一个队列或标志位)的监视器协调执行:
- wait():当前线程释放该对象锁,并进入等待队列;直到被其他线程调用 notify() 或 notifyAll() 唤醒,且重新竞争到锁后才继续执行
- notify():唤醒等待队列中的一个线程(不保证哪一个),被唤醒线程需重新获取锁才能继续
- notifyAll():唤醒所有等待该对象的线程,适用于多个生产者/消费者共存的场景,避免信号丢失
用 Object.wait 实现简单阻塞队列
以一个容量为 1 的共享缓冲区为例(即“一个槽”模型),用 Object 的 wait/notify 控制存取:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
<font color="#888">class SimpleBuffer {
private String data;
private boolean occupied = false;
// 生产者调用
public synchronized void put(String item) throws InterruptedException {
while (occupied) { // 使用 while 而非 if,防止虚假唤醒
this.wait(); // 释放锁,等待消费者取走数据
}
data = item;
occupied = true;
this.notifyAll(); // 唤醒可能等待的消费者
}
// 消费者调用
public synchronized String take() throws InterruptedException {
while (!occupied) { // 同样用 while 防止虚假唤醒
this.wait(); // 释放锁,等待生产者放入数据
}
String result = data;
data = null;
occupied = false;
this.notifyAll(); // 唤醒可能等待的生产者
return result;
}
}</font>
为什么必须用 synchronized + while 循环?
这是正确使用 wait 机制的核心约束:
- synchronized:wait/notify 必须在持有对象锁的前提下调用,否则抛出 IllegalMonitorStateException
- while 循环判断条件:线程被唤醒后,条件未必已满足(如被其他线程抢先修改、虚假唤醒),必须重新检查业务条件是否成立
- notifyAll 而非 notify:在多生产者或多消费者场景下,notify 可能只唤醒同类型线程(如两个消费者都在 wait,notify 唤醒另一个消费者),导致死锁;notifyAll 确保至少有一个合适线程被唤醒
与现代工具类的对比
虽然 Object 的 wait/notify 是基础,但实际开发中更推荐使用 java.util.concurrent 包中的高级抽象:
- BlockingQueue(如 ArrayBlockingQueue、LinkedBlockingQueue):内部封装了 wait/notify 逻辑,线程安全、支持超时、可中断,API 更清晰
- ReentrantLock + Condition:提供比 synchronized 更灵活的锁控制(如多个等待队列、可中断等待、公平性配置)
- 直接操作 Object 的 wait/notify 主要用于学习原理、编写底层同步工具,或极简嵌入式场景
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










