ArrayBlockingQueue是Java中基于ReentrantLock和Condition实现的线程安全有界阻塞队列,支持生产者-消费者模式,通过notFull和notEmpty条件变量协调阻塞与唤醒,容量固定、不支持null,具备内存可控、吞吐稳定等优势。

ArrayBlockingQueue 是 Java 中线程安全的有界阻塞队列,内部基于 ReentrantLock 和 Condition 实现,天然支持生产者-消费者模式,无需额外加锁或 wait/notify 协调。
核心机制:锁 + 条件等待
ArrayBlockingQueue 使用一个可重入锁(ReentrantLock)保护整个队列操作,并维护两个 Condition:
- notFull:当队列满时,生产者 await() 在此条件上;有元素被消费后,消费者 signal() 唤醒等待的生产者
- notEmpty:当队列空时,消费者 await() 在此条件上;有新元素入队后,生产者 signal() 唤醒等待的消费者
所有 put/take 操作都自动完成「检查 → 阻塞等待 → 执行 → 唤醒」闭环,开发者只需调用 API,不用手动管理线程协作逻辑。
典型生产者-消费者代码结构
使用 ExecutorService 启动多个生产者和消费者线程,共享同一个 ArrayBlockingQueue 实例即可:
立即学习“Java免费学习笔记(深入)”;
ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
// 生产者
ExecutorService producerPool = Executors.newFixedThreadPool(2);
producerPool.submit(() -> {
for (int i = 0; i < 5; i++) {
try {
String item = "msg-" + i;
queue.put(item); // 队列满则阻塞
System.out.println("Produced: " + item);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
// 消费者
ExecutorService consumerPool = Executors.newFixedThreadPool(3);
consumerPool.submit(() -> {
for (int i = 0; i < 5; i++) {
try {
String item = queue.take(); // 队列空则阻塞
System.out.println("Consumed: " + item);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
注意:put/take 是阻塞式方法;若想非阻塞,可用 offer(e, timeout, unit) 或 poll(timeout, unit)。
关键注意事项
- 容量固定:构造时必须指定大小,不可扩容;超出容量的 put 会永久阻塞(除非被中断)
- 公平性可选:构造函数支持 fair 参数(默认 false),设为 true 可保证等待线程按 FIFO 获取锁,避免饥饿但性能略低
- 不支持 null:put(null) 会立即抛出 NullPointerException
- 中断响应:put/take 在阻塞中可被 interrupt 中断,并抛出 InterruptedException,务必正确处理并恢复中断状态
对比其他阻塞队列
相比 LinkedBlockingQueue(基于链表、可选无界)、PriorityBlockingQueue(无界、支持优先级),ArrayBlockingQueue 的优势在于:
- 内存占用更可控(数组预分配,无节点对象开销)
- 吞吐量稳定(避免链表节点 GC 压力)
- 适合对延迟敏感、容量明确的场景(如消息缓冲池、任务节流)
缺点是无法动态扩容,且单锁设计在极高并发下可能成为瓶颈(不过多数业务场景已足够)。


















