java中wait()和notifyall()配合synchronized可实现生产者消费者模型,核心是共享缓冲区、同步控制及条件等待:队列满时生产者wait,空时消费者wait,所有操作需在同步块内,且wait/notifyall必须在同一锁对象上调用。

Java中用wait()和notify()/notifyAll()配合synchronized可以实现线程间协作,是生产者消费者模型最基础、最典型的实现方式。
核心逻辑:共享缓冲区 + 同步控制
生产者往共享队列(如ArrayList或LinkedList)添加数据,消费者从中取走数据。关键在于:当队列满时生产者等待,当队列空时消费者等待。所有对队列的读写操作必须在同步块内完成,且wait()和notifyAll()必须在同一个锁对象上调用。
- 使用一个对象(比如队列本身或专门的锁对象)作为监视器(monitor)
- 生产者调用
wait()前必须确认队列已满;消费者调用wait()前必须确认队列为空 - 每次插入或移除后,都要调用
notifyAll()唤醒所有等待线程——因为只唤醒一个可能唤醒错角色(比如唤醒另一个生产者而非消费者)
典型代码结构(以固定容量队列为例)
定义一个带容量限制的共享容器:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
class BoundedBuffer {
private final List<integer> buffer = new ArrayList();
private final int capacity;
public BoundedBuffer(int capacity) {
this.capacity = capacity;
}
public synchronized void produce(int item) throws InterruptedException {
while (buffer.size() == capacity) {
wait(); // 队列满,生产者等待
}
buffer.add(item);
System.out.println("Produced: " + item + ", size=" + buffer.size());
notifyAll(); // 唤醒可能等待的消费者(或其他生产者)
}
public synchronized int consume() throws InterruptedException {
while (buffer.isEmpty()) {
wait(); // 队列空,消费者等待
}
int item = buffer.remove(0);
System.out.println("Consumed: " + item + ", remaining=" + buffer.size());
notifyAll(); // 唤醒可能等待的生产者
return item;
}
}</integer>
启动生产者与消费者线程
每个线程循环执行生产或消费动作,注意捕获InterruptedException并合理处理(通常恢复中断状态):
BoundedBuffer buffer = new BoundedBuffer(3);
Thread producer = new Thread(() -> {
for (int i = 0; i {
for (int i = 0; i
<h3>注意事项与常见陷阱</h3>
<p>这种手写<code>wait/notify</code>方式虽经典,但容易出错:</p>
-
永远用
while而非if判断条件:防止虚假唤醒(spurious wakeup)导致逻辑错误 -
不要在静态方法或不同锁对象上混用
wait/notify:必须保证所有线程竞争同一把锁 -
避免在构造器或未完全初始化的对象上调用
wait:否则可能因锁未正确获取而抛IllegalMonitorStateException - 实际项目中更推荐使用
java.util.concurrent包下的高级工具,如BlockingQueue(ArrayBlockingQueue、LinkedBlockingQueue),它们内部已封装好线程安全与等待通知逻辑,更简洁可靠
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










