Java中生产者消费者模式推荐使用BlockingQueue(如ArrayBlockingQueue、LinkedBlockingQueue),其内部通过ReentrantLock和Condition自动实现队列满时生产者阻塞、队列空时消费者阻塞,无需手动处理wait/notify。

Java 中生产者消费者模式下,队列满时生产者阻塞、队列空时消费者阻塞,核心靠 wait/notify 或更推荐的 Lock + Condition 实现线程协作。JDK 自带的 BlockingQueue(如 ArrayBlockingQueue、LinkedBlockingQueue)已封装好这些逻辑,直接调用即可。
使用 BlockingQueue 自动处理阻塞与唤醒
这是最常用、最安全的方式。所有阻塞操作(如 put()、take())内部已通过 ReentrantLock 和 Condition 实现精确等待与唤醒:
-
queue.put(item):队列满时,当前线程自动进入 WAITING 状态,直到有空间被腾出; -
queue.take():队列空时,当前线程自动等待,直到有新元素入队; - 唤醒由另一方线程调用
signal()触发(例如消费者取走元素后,会 signal 生产者线程)。
手动实现:Lock + Condition 精确控制
若需自定义逻辑(如多个条件等待、不同唤醒策略),可用 ReentrantLock 配合两个 Condition:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 定义
notFull条件用于生产者等待队列不满; - 定义
notEmpty条件用于消费者等待队列不空; - 生产者在
put前检查容量,满则notFull.await();成功入队后notEmpty.signal()唤醒消费者; - 消费者同理,在
take前notEmpty.await(),出队后notFull.signal()。
不推荐:synchronized + wait/notify
虽能工作,但存在明显缺陷:
立即学习“Java免费学习笔记(深入)”;
-
notify()可能随机唤醒同类线程(比如唤醒另一个生产者),导致虚假唤醒或死锁; - 无法区分“队列满”和“队列空”两种等待场景,只能共用一个 monitor,需配合 while 循环 + 条件判断(即“必须用 while 而非 if”);
- 没有超时控制、无法中断等待,灵活性差。
关键细节提醒
无论哪种方式,都要注意:
- 所有共享状态(如队列大小、元素数组)的读写,必须在加锁区域内完成;
- await() 必须在循环中检查条件(防止虚假唤醒);
- signal() 应在修改共享状态后调用,确保唤醒时条件已满足;
- 优先选用
BlockingQueue子类,避免重复造轮子;需要公平性或容量限制时,选ArrayBlockingQueue;对吞吐量敏感且允许无界时,可选LinkedBlockingQueue(注意其默认容量为Integer.MAX_VALUE,并非真正无界)。

















