arrayblockingqueue 是线程安全、有界、基于数组的阻塞队列,通过 reentrantlock 和两个 condition 实现阻塞等待与唤醒,适用于生产者-消费者模型。

ArrayBlockingQueue 是 Java 并发包中一个线程安全、有界、基于数组实现的阻塞队列,天然适合用于生产者-消费者模型的缓冲区。它内部通过可重入锁(ReentrantLock)和两个 Condition(notFull / notEmpty)实现线程等待与唤醒,无需手动加锁或 wait/notify。
为什么选 ArrayBlockingQueue 做缓冲区
它具备三个关键特性,直接解决生产者消费者的核心问题:
- 有界性:构造时指定固定容量,防止内存无限增长;当队列满时,生产者调用 put() 会阻塞,直到有空间;队列空时,消费者调用 take() 会阻塞,直到有元素。
- 线程安全:所有操作(offer、poll、put、take)都是原子且同步的,无需额外 synchronized 或 Lock。
- 阻塞语义明确:put/take 是典型的“阻塞直到成功”,比 offer/poll(立即返回 null 或 false)更适合需要强协调的场景。
基础用法:启动一对生产者和消费者
以下是一个最小可运行示例,使用两个线程模拟单生产者单消费者:
ArrayBlockingQueue<string> buffer = new ArrayBlockingQueue(10);
// 生产者线程
new Thread(() -> {
try {
for (int i = 0; i {
try {
for (int i = 0; i
</string>
实际项目中要注意的关键点
真实场景比示例复杂,需关注这几项:
- 异常处理必须恢复中断状态:put/take 声明 throws InterruptedException,捕获后应调用 Thread.currentThread().interrupt(),否则上层逻辑可能无法感知中断信号。
- 避免死锁式 shutdown:若用 ExecutorService 管理线程,关闭前建议先停止生产者(如用 volatile 标志位),再 awaitTermination;不要让生产者还在 put 而消费者已退出,否则生产者可能永远阻塞。
- 容量设置要合理:太小导致频繁阻塞影响吞吐;太大占用过多堆内存,且延迟升高。可根据平均生产/消费速率和容忍延迟估算,例如:最大积压量 ≈ (生产速率 − 消费速率) × 可接受等待时间。
- 不建议混用非阻塞方法:比如一边用 put,一边用 poll(timeout),语义不一致易出错;统一用 put/take 更清晰可靠。
扩展:多生产者多消费者共用同一缓冲区
ArrayBlockingQueue 天然支持任意数量的生产者和消费者共享。只需确保所有线程操作的是同一个实例:
- 多个生产者线程都调用 buffer.put(...) —— 它们会自动排队获取锁,满时各自阻塞;
- 多个消费者线程都调用 buffer.take(...) —— 空时全部等待,有新元素时由队列唤醒其中一个(公平模式下按等待顺序);
- 如需公平调度,构造时传入 true:
new ArrayBlockingQueue(10, true),但会略微降低吞吐量。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











