arrayblockingqueue基于固定大小环形数组、单锁、强有界,缓存友好且内存可控;linkedblockingqueue基于链表节点、双锁、可选有界,吞吐高但gc压力大、内存分散。

选对阻塞队列直接影响线程池的响应速度和系统稳定性。ArrayBlockingQueue 和 LinkedBlockingQueue 虽都实现 BlockingQueue 接口,但底层设计差异显著,不能简单互换。
底层结构与内存行为不同
ArrayBlockingQueue 使用**固定大小的环形数组**,初始化时必须指定容量,内存一次性分配、连续布局:
- CPU 缓存友好,遍历和访问局部性高
- 无对象创建开销,元素直接存入预分配槽位
- 内存占用确定,不会因任务激增而意外膨胀
LinkedBlockingQueue 基于**链表节点(Node)**,每个元素封装为一个独立对象:
- 每入队一次就 new 一个 Node,带来 GC 压力(尤其高频场景)
- 内存分散,访问跳转多,缓存命中率低
- 默认容量是
Integer.MAX_VALUE,看似“无界”,实则极易耗尽堆内存
锁机制决定并发吞吐能力
ArrayBlockingQueue 采用**单把 ReentrantLock**,put 和 take 共享同一把锁:
- 生产者阻塞时,消费者也无法取数据;反之亦然
- 适合中低并发或对延迟敏感但任务量稳定的场景
LinkedBlockingQueue 使用**分离双锁**:putLock 管插入,takeLock 管取出:
- 生产者和消费者可完全并行操作,互不干扰
- 高并发下吞吐量明显更高,适合后台异步任务、日志缓冲等写读密集型场景
容量控制与适用边界清晰
ArrayBlockingQueue 是**强有界队列**:
- 容量不可变,天然防止 OOM,适合资源受限环境(如网关限流、订单撮合)
- 配合拒绝策略(如
AbortPolicy)能快速暴露上游过载问题
LinkedBlockingQueue 支持**显式有界或默认无界**:
- 若不设容量,等于放弃背压控制,风险极高
- 设容量后虽有界,但因链表+对象分配,内存开销仍大于数组方案
- 适合需要弹性缓冲、且消费能力相对稳定的长周期任务
公平性与一致性细节
ArrayBlockingQueue 支持构造时传入 fair = true,启用公平锁:
- 线程按等待顺序获取锁,避免饥饿,但上下文切换成本上升
-
size()通过全局锁保证强一致性
LinkedBlockingQueue **仅支持非公平锁**:
- 不保证线程调度顺序,但锁获取更快,符合高吞吐设计目标
-
size()用原子变量计算,无需加锁,但可能短暂滞后于实际状态
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











