arrayblockingqueue容量固定不可扩容,底层为object[]数组;linkedblockingqueue默认容量为integer.max_value,并非真正无界,两者均为有界队列,区别仅在于容量锁定时机。

ArrayBlockingQueue 必须指定容量,且无法动态扩容
它底层是固定大小的 Object[] 数组,构造时传入的 capacity 就是内存上限,之后不可更改。哪怕只差一个元素,put() 就会阻塞,offer() 直接返回 false。
- 常见错误:用默认构造器——编译不通过,必须写
new ArrayBlockingQueue(10) - 适用场景:任务调度限流、资源池(如数据库连接池)等需要硬性容量控制的地方
- 注意公平性参数:
new ArrayBlockingQueue(10, true)启用公平锁,线程按等待顺序获取,但吞吐下降明显,非必要别开
LinkedBlockingQueue 默认“无界”,但本质仍是逻辑有界
它的默认构造器等价于 new LinkedBlockingQueue(Integer.MAX_VALUE),不是真无限,只是上限极大;一旦持续写入快于消费,堆内存会被撑爆,OOM 风险真实存在。
- 常见错误现象:日志突然卡住、Full GC 频繁、应用 OOM 崩溃,查堆 dump 发现
Node对象占满老年代 - 正确做法:显式设容量,例如
new LinkedBlockingQueue(1024),尤其在线程池workQueue中必须这么做 - 性能差异:它用
putLock和takeLock分离读写,高并发下吞吐优于ArrayBlockingQueue;但每个元素都新建Node对象,GC 压力略大
有界性 ≠ 是否能扩容,而是“容量上限是否在构造时锁定”
很多人误以为 LinkedBlockingQueue “可扩容”所以更灵活,其实两者都是有界队列——区别只在于“界”的确定时机和方式。
-
ArrayBlockingQueue:界由数组长度决定,创建即固化,内存紧凑 -
LinkedBlockingQueue:界由capacity字段控制,未显式设置时为Integer.MAX_VALUE,仍受 JVM 堆限制 - 关键提醒:“无界”只是 API 层的简化说法,JVM 里没有真正无界的容器;所有队列最终都受限于可用内存
线程池中选哪个?看你是要控流,还是要吞吐
在 ThreadPoolExecutor 构造参数里,workQueue 是最易被随意配置的一环,也是线上事故高发点。
- 选
ArrayBlockingQueue:你明确知道最大积压任务数,比如秒杀系统要求最多缓存 5000 个下单请求,超了就走拒绝策略 - 选
LinkedBlockingQueue(显式设容):消费速率波动大,希望入队/出队尽量不互相阻塞,比如异步通知服务,短信和邮件发送速度差异大 - 绝对避免:
new LinkedBlockingQueue()直接丢进线程池——等于把背压机制交给 GC,而不是业务逻辑










