java实现生产者消费者模型推荐使用blockingqueue,它内置线程安全与阻塞机制;也可用synchronized+wait/notify或reentrantlock+condition手动实现,但需注意while校验、notifyall、可见性及中断处理。

Java 中实现生产者消费者模型,核心是解决线程间协作与资源同步问题:生产者往共享缓冲区放数据,消费者从中取数据,二者需避免竞争、空取、满写,并保证可见性与原子性。推荐使用 阻塞队列(BlockingQueue),它已内置线程安全与等待/通知机制,简洁可靠。
用 BlockingQueue 实现(推荐)
这是最简单、最健壮的方式。JDK 提供的 ArrayBlockingQueue、LinkedBlockingQueue 等都实现了线程安全的 put/take 操作,自动处理阻塞与唤醒。
- put(E e):若队列满,则阻塞直到有空间;
- take():若队列空,则阻塞直到有元素;
- 无需手动加锁、调用 wait/notify,也不用判断条件循环。
示例关键代码:
private final BlockingQueue
Producer(BlockingQueue
public void run() {
try {
for (int i = 0; i String item = "item-" + i;
System.out.println("Produced: " + item);
queue.put(item); // 自动阻塞
TimeUnit.MILLISECONDS.sleep(100);
}
} catch (InterruptedException e) { Thread.currentThread().interrupt(); }
}
}
用 synchronized + wait/notify 手动实现
适合学习底层原理或需精细控制等待条件的场景。关键点:必须在 synchronized 块中调用 wait/notify,且要用 while 循环检查条件(防止虚假唤醒)。
- 共享缓冲区需用 volatile 或 synchronized 保证可见性;
- 生产者在满时 wait(),放入后 notifyAll();
- 消费者在空时 wait(),取出后 notifyAll();
- 务必用 while 判断条件,不用 if。
例如:
synchronized (buffer) {
while (buffer.size() == MAX_SIZE) {
buffer.wait(); // 等待有空位
}
buffer.add(item);
buffer.notifyAll(); // 唤醒可能等待的消费者
}
用 ReentrantLock + Condition 实现
比 synchronized 更灵活,可定义多个等待队列(如 separate notEmpty / notFull condition),避免 notifyAll 的“惊群效应”。
- 用
lock.newCondition()创建两个 condition; - 生产者 await() 在 notFull 上,signal() notEmpty;
- 消费者 await() 在 notEmpty 上,signal() notFull;
- 仍需在 try-finally 中确保 unlock(),并用 while 循环检查状态。
注意事项与常见陷阱
- 不要用 if 判断条件:wait 被唤醒后状态可能已变,必须用 while 再校验;
- notify() vs notifyAll():除非明确只有一个线程等待,否则优先用 notifyAll();
- 共享变量要保证可见性:Buffer 大小等状态变量建议用 volatile,或全部操作包裹在同步块内;
-
中断处理:阻塞方法(如 put/take/wait)响应中断,需捕获 InterruptedException 并恢复中断状态(
Thread.currentThread().interrupt())。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











