本篇博文主要介绍线程池如何接收并处理任务,在此之前你需要了解下面两个知识点:
了解上面两个知识点才能更好的理解本篇文章。
0.引言
线程池处理任务的逻辑决定于当前线程数(workerCount)的大小与核心线程数(corePoolSize)、最大线程数(maximumPoolSize)大小的关系。为了便于理解,先把执行逻辑画出来:
关于线程池如何接收并处理任务的所有逻辑都在上面那个图,我们后面分析也是根据图的逻辑来的,所以可以先把图理解,后面的源码分析才不会头晕目眩。
1.execute(Runnable)
ThreadPoolExecutor只提供一个接收Runnable任务的方法executor(Runnable)。核心逻辑也在该方法内,所以有必要对该方法的源码进一步分析。
线程池通过execute(Runnable)方法接收放入线程池的任务。
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
处理的过程分为五个步骤:
- 如果提交的任务为null,则抛出NPE异常;
- 如果运行的线程数小于corePoolSize,则新创建一个线程并执行该任务;这个过程由addWorker(command,true)方法完成;
- 如果线程池还在运行且等待队列没有满,则把任务放入等待队列;
- 如果线程池还在运行但队列已经放满,则尝试创建新的线程并执行该任务;
- 如果线程池没有运行,则直接执行拒绝策略;
从以上5个的简单的