Java实现生产者消费者模型有三种核心方式:一是synchronized+wait/notify,需用while循环防虚假唤醒;二是推荐使用BlockingQueue(如ArrayBlockingQueue),自动阻塞唤醒;三是ReentrantLock+Condition,支持多条件灵活控制。

Java 中实现生产者消费者模型,核心在于线程间共享数据的**安全访问**与**协作等待/唤醒**。不依赖轮询,而是通过同步机制让生产者在缓冲区满时等待、消费者在空时等待,有数据/空间时精准唤醒对方。
使用 synchronized + wait/notify 实现(基础可靠)
这是最经典、易理解的方式,适用于任何 JDK 版本:
- 定义一个共享缓冲区(如 ArrayList 或 Queue),用 synchronized 方法或代码块保护所有读写操作
- 生产者中:若缓冲区已满(queue.size() == capacity),调用 wait() 暂停;成功放入后调用 notifyAll() 唤醒可能等待的消费者
- 消费者中:若缓冲区为空(queue.isEmpty()),调用 wait() 暂停;成功取出后同样调用 notifyAll() 唤醒可能等待的生产者
- 注意:必须用 while 循环判断条件,不能用 if —— 防止虚假唤醒(spurious wakeup)
使用 BlockingQueue(推荐,简洁高效)
JDK 提供的线程安全阻塞队列是最佳实践,无需手动处理锁和等待逻辑:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 选用 ArrayBlockingQueue(有界)、LinkedBlockingQueue(可选界)或 SynchronousQueue(手递手传递)
- 生产者调用 put(item):队列满时自动阻塞,直到有空间;消费者调用 take():队列空时自动阻塞,直到有元素
- 代码极简:不用写 synchronized、wait、notify,异常安全,性能优化成熟
- 示例:queue.put("data"); 和 String s = queue.take(); 即完成协作
使用 ReentrantLock + Condition(灵活可控)
适合需要更细粒度控制(如多个等待条件)的场景:
立即学习“Java免费学习笔记(深入)”;
- 创建 ReentrantLock 和两个 Condition:一个用于“非满”(notFull),一个用于“非空”(notEmpty)
- 生产者在满时 notFull.await(),成功后 notEmpty.signal();消费者在空时 notEmpty.await(),成功后 notFull.signal()
- 相比 synchronized,支持公平锁、可中断等待、多个 condition 分离信号,但代码稍长
关键提醒:避免常见陷阱
无论哪种方式,以下几点直接影响协作可靠性:
- 共享变量必须是同一个对象实例,不能每个线程 new 一个缓冲区
- 生产者和消费者线程需共用同一把锁(synchronized 对象 / 同一 Lock 实例 / 同一 BlockingQueue 实例)
- 不要用 Thread.sleep() 替代 wait/notify 或阻塞操作——它不释放锁,且无法被精确唤醒
- 关闭资源时注意线程中断处理(如 BlockingQueue 的 poll(timeout) 可响应中断)

















