arrayblockingqueue 是 java 并发包中线程安全、基于数组的有界阻塞队列,采用 reentrantlock 和两个 condition 实现精确阻塞唤醒;初始化需指定固定容量,可选公平性策略;生产者用 put()(阻塞)或 offer()(非阻塞),消费者用 take()(阻塞)或 poll()(非阻塞);常作为 threadpoolexecutor 的工作队列,配合拒绝策略防 oom。

ArrayBlockingQueue 是 Java 并发包(java.util.concurrent)中一个线程安全、基于数组实现的有界阻塞队列,适合在生产者-消费者模型中高效协调多线程存取。它内部使用可重入锁(ReentrantLock)和两个 Condition(notFull / notEmpty)实现精确的阻塞与唤醒,避免无谓轮询,性能稳定且内存可控。
初始化时明确容量并选择公平性策略
构造 ArrayBlockingQueue 必须指定固定容量,这是其“有界”的核心约束;同时可选是否启用公平锁——公平模式下线程按等待顺序获取锁,减少饥饿但吞吐略低;非公平(默认)则更注重响应速度。
- 推荐显式传入 capacity,例如:new ArrayBlockingQueue
(1024) - 高吞吐场景(如日志缓冲)用默认非公平策略;对响应一致性要求高(如任务调度)可设为 true
- 容量不宜过大,否则内存占用高且阻塞时间变长;也不宜过小,否则频繁阻塞影响吞吐
生产者用 put() 或 offer() 控制入队行为
put() 是阻塞式插入:队列满时线程挂起,直到有空间再继续;offer() 是非阻塞尝试:立即返回 true/false,适合需快速失败或自定义重试逻辑的场景。
- 常规生产逻辑优先用 queue.put(item),语义清晰且无需手动处理满队列
- 若业务允许丢弃或降级(如监控数据采样),可用 queue.offer(item) 配合 if 判断
- 避免在循环中反复调用 offer() + Thread.sleep() 自旋等待,应改用 put() 或带超时的 offer(item, timeout, unit)
消费者用 take() 或 poll() 安全取值
take() 阻塞等待元素,适合持续消费的守护线程;poll() 立即返回,适合需配合其他逻辑(如定时检查、批量处理)的场景。
- 典型消费者线程写法:while (!Thread.interrupted()) { String s = queue.take(); process(s); }
- 若需限时等待(如防止卡死),用 poll(5, TimeUnit.SECONDS),返回 null 表示超时
- 注意不要在未判空情况下直接调用 poll() 后解引用,应始终检查返回值是否为 null
结合 ExecutorService 实现轻量级任务管道
将 ArrayBlockingQueue 作为线程池的阻塞工作队列,能天然承接突发任务、平滑流量峰值,并利用其容量限制防止 OOM。
- 创建时传入队列:new ThreadPoolExecutor(core, max, keepAlive, unit, new ArrayBlockingQueue(100))
- 拒绝策略建议用 DiscardPolicy 或 CallerRunsPolicy,避免抛出异常中断流程
- 队列容量应与线程池参数协同设计:例如 core=4、queue=100 时,最多积压 100 个待处理任务,超出则触发拒绝策略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











