选有界队列(如ArrayBlockingQueue)是保障线程池稳定的关键,容量需按“峰值QPS×平均耗时×1.5”公式计算,避免无界队列导致OOM;SynchronousQueue仅适用于极短任务。

选对阻塞队列,是线程池不崩、不慢、不爆内存的关键一步。它不是越大越好,也不是越快越优,而要根据任务节奏、系统资源和失败容忍度来定。
优先用有界队列:ArrayBlockingQueue 是稳态首选
无界队列(如默认的 LinkedBlockingQueue 不设容量)看似“永不拒绝”,实则把压力延后——任务越积越多,堆内存持续上涨,GC 压力陡增,最终 OOM。线上事故里,超 60% 的内存泄漏与无界队列直接相关。
推荐用 ArrayBlockingQueue,原因很实在:
- 容量固定,能真实反映系统承载能力
- 触发拒绝策略早,问题暴露在流量入口,而非深夜告警
- 数组结构,读写性能稳定,无链表扩容开销
队列容量不能拍脑袋:按 QPS × 耗时 × 缓冲系数算
容量不是经验数,而是可推演的业务指标:
立即学习“Java免费学习笔记(深入)”;
建议公式: 队列容量 ≈ 预估峰值 QPS × 平均单任务处理时长(秒)× 1.5
例如:
- 接口峰值 QPS = 200,平均耗时 = 150ms → 容量 ≈ 200 × 0.15 × 1.5 = 45 → 取整为 64
- 日志异步推送,QPS = 500,耗时 = 80ms → 容量 ≈ 500 × 0.08 × 1.5 = 60 → 取整为 64 或 128(留余量)
超过该值的任务,就该由最大线程数兜底或拒绝策略接管,而不是全塞进内存等爆炸。
慎用 SynchronousQueue:适合极短任务,不适合常规业务
SynchronousQueue 本质是“手递手”传输,不存任务。它要求线程必须即时可用,否则直接触发拒绝。
只适合两类场景:
- 任务执行极快(
- 配合 cachedThreadPool 使用,但需严格限制 maximumPoolSize,否则线程数失控
普通 HTTP 处理、DB 查询、Kafka 发送等中长耗时任务,用它等于主动放弃缓冲能力,极易因瞬时抖动触发大量拒绝。
别碰 PriorityBlockingQueue 和 DelayQueue:除非真需要排序或延时
它们带来额外锁竞争和 CPU 开销,PriorityBlockingQueue 还有对象比较成本。日常业务中,任务天然无优先级,强行加优先级反而打乱调度公平性,吞吐常下降 15%~30%。
真正需要延时/定时的场景(如重试、延迟通知),应交由 ScheduledThreadPoolExecutor 或外部消息中间件处理,而非在线程池队列里硬扛。


















