可以使用object的wait()和notifyall()配合synchronized实现线程安全的生产者消费者模式,核心是用共享缓冲区作锁,通过while循环中wait()等待、notifyall()唤醒协调满/空状态,确保线程安全与避免虚假唤醒。

可以用 Object 的 wait() 和 notifyAll() 配合 synchronized 实现线程安全的生产者消费者模式,核心是用共享对象作锁,通过等待/唤醒机制协调线程行为。
共享缓冲区与同步控制
定义一个带容量限制的队列(如 LinkedList),所有对它的读写操作必须在 synchronized 块中进行,锁对象通常是该缓冲区自身。这样能保证同一时刻只有一个线程修改状态,避免竞态条件。
例如:
synchronized (buffer) {if (buffer.size() >= capacity) {
buffer.wait(); // 生产者等待空间
}
buffer.add(item);
buffer.notifyAll(); // 唤醒可能等待的消费者
}
生产者逻辑:满则等待,添加后通知
生产者每次尝试放入数据前,先检查缓冲区是否已满:
- 若满,调用 wait() 挂起当前线程,并释放锁,直到被唤醒
- 若未满,执行添加操作,然后调用 notifyAll() 告知所有等待线程状态可能已变
- 注意 wait() 必须在 while 循环中调用,防止虚假唤醒导致越界或空指针
消费者逻辑:空则等待,取走后通知
消费者每次尝试获取数据前,先检查缓冲区是否为空:
- 若空,调用 wait() 挂起并释放锁
- 若非空,取出元素,然后调用 notifyAll() 唤醒可能等待的生产者
- 同样使用 while 循环判断条件,不依赖单次唤醒的“准确性”
关键细节与常见陷阱
务必牢记以下几点,否则容易出现死锁、丢失通知或无限等待:
- wait()、notify()、notifyAll() 只能在 synchronized 方法或块中调用,否则抛 IllegalMonitorStateException
- 永远用 while 而不是 if 包裹 wait(),因为线程被唤醒后条件未必成立
- 优先使用 notifyAll() 而非 notify(),避免唤醒错线程导致部分线程永久等待
- 共享变量(如 buffer.size())的读写需受同一把锁保护,不能在 synchronized 外直接访问










