线程池处理任务的过程?
基于 JDK 官方 ThreadPoolExecutor 源码行为总结,标准的线程池处理任务流程如下:
1. 背景(线程池主要组成)
在执行任务前,线程池中有这些重要组件:
- corePoolSize:核心线程数
- maximumPoolSize:最大线程数
- workQueue:阻塞任务队列
- threadFactory:线程工厂
- handler(RejectedExecutionHandler):拒绝策略
2. 任务提交
- 调用
executor.execute(Runnable task)或submit(Callable task)提交任务。
3. 判断当前运行线程数量(workerCount)是否小于 corePoolSize
如果小于 corePoolSize:
✅ ➔ 直接创建一个新线程来执行这个任务。
- 通过
threadFactory创建线程并启动。 - 新线程开始处理提交的任务。
(注意:这个新建线程属于核心线程。)
如果大于等于 corePoolSize:
⏩ 进入下一步。
4. 尝试将任务加入工作队列(workQueue.offer)
如果队列未满(offer 成功):
✅ ➔ 把任务放进等待队列,等待已有线程来处理。
- 核心线程会不断从队列中取任务执行。
如果队列已满(offer 失败):
⏩ 进入下一步。
5. 判断当前线程数(workerCount)是否小于 maximumPoolSize
如果小于 maximumPoolSize:
✅ ➔ 再创建一个新线程来执行这个任务。
(注意:这个新线程不是核心线程,是扩展线程(非核心线程)。)
如果等于或大于 maximumPoolSize:
⏩ 进入下一步。
6. 执行拒绝策略(RejectedExecutionHandler)
- 当线程数已到上限、队列也满了,就调用拒绝策略。
- 拒绝策略可以是:
- 抛异常(默认:AbortPolicy)
- 由提交任务的线程自己执行(CallerRunsPolicy)
- 丢弃最新任务(DiscardPolicy)
- 丢弃最老任务并重试(DiscardOldestPolicy)
(小技巧:面试时加一句,一般重要业务还会加日志报警!)
7. 任务执行
- 核心线程或扩展线程从队列中不断拉取任务执行(
Runnable.run())。 - 任务执行完,线程继续取下一个任务。
- 如果线程空闲超时(超过 keepAliveTime),且是非核心线程,就会被回收(销毁)。
线程池任务处理过程总结版
一张标准流程图:
提交任务
↓
核心线程数 < corePoolSize?
是 → 新建核心线程执行
否 → 入队列
↓
队列满了?
是 → 当前线程数 < maximumPoolSize?
是 → 创建非核心线程执行
否 → 执行拒绝策略
否 → 排队等待线程处理
小技巧:面试时可以再加一句总结
“线程池本质是通过合理的线程数控制和任务排队机制,最大化资源利用率,防止系统过载,同时保证任务尽可能快速被处理。”
更多详细内容请关注其他相关文章!