arrayblockingqueue 是 java 并发包中基于固定长度数组实现的线程安全有界阻塞队列,使用单个 reentrantlock 加锁并配合 notempty 和 notfull 两个 condition 实现高效生产者-消费者协作。

ArrayBlockingQueue 是 Java 并发包(java.util.concurrent)中一个线程安全的、有界阻塞队列,底层用固定长度的数组实现,采用单个 ReentrantLock 加锁来保障所有操作的原子性与可见性。
有界数组结构决定容量不可变
创建时必须指定容量(capacity),内部使用 Object[] 数组存储元素,长度固定。队列满时 put() 阻塞,空时 take() 阻塞,天然支持生产者-消费者模型的流量控制。
- 容量在构造时确定,运行期无法扩容或缩容
- 数组下标通过取模运算(head/tail % array.length)实现环形缓冲逻辑
- 不支持 null 元素,插入 null 会抛 NullPointerException
单 ReentrantLock 统一保护所有操作
不同于 ConcurrentLinkedQueue 的无锁设计,ArrayBlockingQueue 使用一个全局可重入锁(fair 或 non-fair 模式可选),所有入队(offer/put)、出队(poll/take)、检查(peek/size)等操作均需获取该锁。
- 锁对象由构造器传入或默认创建,同一实例所有操作共用一把锁
- 非公平模式(默认)吞吐量更高;公平模式按等待顺序调度,避免饥饿但性能略低
- size()、isEmpty() 等读操作也加锁——这点区别于 CopyOnWriteArrayList 等读多写少场景优化的集合
条件变量分离等待逻辑
虽只用一把锁,但内部维护两个 Condition 实例:notEmpty 和 notFull,分别用于阻塞/唤醒消费者和生产者。
- put() 在队列满时 await(notFull),成功入队后 signal(notEmpty)
- take() 在队列空时 await(notEmpty),成功出队后 signal(notFull)
- 这种“单锁 + 双条件”设计避免了 notifyAll 带来的无效唤醒,提升调度效率
适合明确容量、强调强一致性的场景
由于锁粒度较粗(全队列串行),高并发写/读混合时吞吐可能低于 LinkedBlockingQueue(双锁)或 SynchronousQueue(无缓冲),但语义更简单、内存占用可控、边界行为确定。
- 典型用途:日志收集缓冲、任务节流队列、资源池请求排队
- 若需动态容量或极高并发吞吐,可考虑 LinkedBlockingQueue(可选容量上限)或 Disruptor 等专用框架
- 注意:remove(Object) 和 contains(Object) 遍历全数组且全程持锁,慎用于大容量队列
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











