一、线程池执行流程
JavaThreadPoolExecutor线程池的任务调度逻辑,核心实现在execute()方法。当向线程池提交任务时,会按照下面这套固定流程处理:`
1. 提交任务
调用线程池execute()提交任务,线程池开始判断当前存活工作线程数量。
2.判断是否小于核心线程数 corePoolSize
- 如果存活线程数小于 corePoolSize:直接新建核心线程来执行这个任务。
- 如果存活线程数大于等于 corePoolSize:不会立刻新建线程,尝试把任务放进工作队列 workQueue。
3.判断工作队列workQueue 是否已满
- 队列未满:任务入队排队,等待空闲线程去队列里取任务执行。
- 队列已满:队列无法接收新任务,继续判断当前存活线程数量。
4.判断是否达到最大线程数 maximumPoolSize
- 存活线程数小于 maximumPoolSize:新建非核心线程,直接执行当前任务。
- 存活线程数等于 maximumPoolSize:线程池资源全部耗尽,触发拒绝策略处理任务。
5.执行拒绝策略
如果当前存活线程数达到了 maximumPoolSize 最大线程数,直接执行拒绝策略处理(如抛出异常、丢弃任务等)。
6.执行任务
无论是创建的核心线程、非核心线程,还是分配的空闲线程,最终都会走到执行线程任务这一步。
二、源码实现
代码如下(示例):
publicvoidexecute(Runnablecommand){if(command==null)thrownewNullPointerException();intc=ctl.get();// 1. 判断存活线程数 < corePoolSize,创建核心线程if(workerCountOf(c)<corePoolSize){if(addWorker(command,true))return;c=ctl.get();}// 2. 判断是否入队成功if(isRunning(c)&&workQueue.offer(command)){// 入队成功,二次检查是否需要补充线程intrecheck=ctl.get();if(!isRunning(recheck)&&remove(command))reject(command);elseif(workerCountOf(recheck)==0)addWorker(null,false);}// 3. 队列已满,尝试创建非核心线程elseif(!addWorker(command,false)){// 4. 创建失败(达到 maximumPoolSize),执行拒绝策略reject(command);}}流程总结
核心线程满 → 进队列 → 队列满 → 建非核心线程 → 最大线程满 → 拒绝策略。