ExecutorService任务队列
在 Java 中,ExecutorService 的任务队列指的是:
当把任务提交给线程池后,如果线程不够用,任务会被放进一个“等待队列”,这个队列就是任务队列(work queue)。
下面从 原理 → 常见队列类型 → 示例 → 注意事项 系统说明。
一、ExecutorService 的任务执行流程(核心)
以 ThreadPoolExecutor 为例(最常用实现):
ExecutorService executor = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
unit,
workQueue
);
提交任务时的执行顺序
- 核心线程是否已满?
- 否 → 创建核心线程执行任务
- 核心线程已满?
- 是 → 任务进入 任务队列(workQueue)
- 队列是否已满?
- 否 → 放入队列等待
- 队列已满?
- 是 → 是否还能创建非核心线程(< maximumPoolSize)
- 能 → 创建新线程执行
- 不能 → 执行 拒绝策略
- 是 → 是否还能创建非核心线程(< maximumPoolSize)
✅ 任务队列在整个流程中处于第 2 / 3 步
二、常见的任务队列类型
1️⃣ LinkedBlockingQueue(最常用)
new LinkedBlockingQueue<>()
- 无界队列(默认 Integer.MAX_VALUE)
- 特点:
- 几乎不会触发非核心线程
- maximumPoolSize 基本无效
- 适用:
- 任务量不可控
- 希望任务排队执行
⚠️ 风险:可能 OOM
2️⃣ ArrayBlockingQueue(有界队列)
new ArrayBlockingQueue<>(100)
- 固定容量
- 特点:
- 队列满 → 才可能创建非核心线程
- 适用:
- 希望控制资源
- 防止任务无限堆积
✅ 推荐生产环境使用
3️⃣ SynchronousQueue(直接交付)
new SynchronousQueue<>()
- 不存任务
- 特点:
- 每个任务必须立刻交给线程
- 没有空闲线程 → 创建新线程或拒绝
- 适用:
- 高吞吐、低延迟
- CachedThreadPool 默认使用
4️⃣ PriorityBlockingQueue(优先级队列)
new PriorityBlockingQueue<>()
- 按优先级执行任务
- 无界
- 任务需实现
Comparable
三、示例对比
✅ 使用有界队列(推荐)
ExecutorService executor = new ThreadPoolExecutor(
2,
4,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(10),
new ThreadPoolExecutor.AbortPolicy()
);
- 核心线程:2
- 最大线程:4
- 队列容量:10
- 超过 → 抛异常
❌ 不推荐(无界队列)
ExecutorService executor = Executors.newFixedThreadPool(10);
等价于:
new ThreadPoolExecutor(
10, 10, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>()
);
⚠️ 队列无界,可能堆积大量任务
四、如何查看任务队列中的任务?
ThreadPoolExecutor tpe = (ThreadPoolExecutor) executor;
BlockingQueue queue = tpe.getQueue();
System.out.println("队列中等待的任务数:" + queue.size());
⚠️ 只能查看数量,不能直接操作任务
五、任务队列相关常见问题
❓ 任务提交后一定会立刻执行吗?
❌ 不一定
→ 可能进入队列等待
❓ 队列满了怎么办?
→ 触发:
- 创建非核心线程
- 或执行拒绝策略
❓ 如何防止任务堆积?
✅ 做法:
- 使用 有界队列
- 合理设置
maximumPoolSize - 自定义拒绝策略(如记录日志、降级)
六、一句话总结
ExecutorService 的任务队列是线程池用于缓存等待执行任务的地方,队列类型直接决定了线程池的行为和稳定性。
如果你愿意,我可以:
- 画一张 线程池执行流程图
- 结合 **实际业务场景(如接口限流、异步日志)**给你选型建议