通过前面的章节,我们学习了可以通过ThreadPoolExecutor来创建一个线程池。
那么接下来我们分析一下ThreadPoolExecutor的源码,看看它具体是如何工作的。
我们看一下使用execute(Runnable task)执行一个任务的时候,到底发生了什么(代码进过简化):
先简单描述一下当我们提交一个任务到线程池中后发生了什么:
具体源码如下:
public void execute(Runnable task) {
//取出当前线程池活跃的线程数。
//ctl是一个原子类型的对象(final AtomicInteger ctl),用来保存当前线程池的线程数以及线程池的状态。
int c = ctl.get();
//如果当前的活跃线程数小于核心线程数,即使现在有空闲线程,也创建一个新的线程,去执行这个任务
if (workerCountOf(c) < corePoolSize) {
//创建一个新的线程,去执行这个任务。
if (addWorker(task, true))
return;
//如果执行到这一句说明任务没有分配成功。
//所以获得当前线程池状态值,为后面的检查做准备。
c = ctl.get();
}
//如果大于核心线程数,检查一下线程池是否还处于运行状态,并尝试把任务放入到blockingQueue任务队列中。
if (isRunning(c) && workQueue.offer(task)) {
//这里再次检查一下线程池的状态
int recheck = ctl.get();
if (! isRunning(recheck) && remove(task))
//如果线程池不处于运行状态的话,就把我们刚才添加进任务队列中的任务移出,并拒绝这个任务。
reject(task);
//检查如果当前线程池中的线程数,如果为0了,就为线程池创建新线程(因为有可能之前存活的线程在上一次检查过后死亡了)
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//执行到这一句,说明队列满了。这时,如果当前线程池中的线程数还没有超过最大线程数,就创建一个新的线程去执行这个任务,如果失败就拒绝这个任务。
else if (!addWorker(task, false))
reject(task);
}
以上就是ThreadPoolExecutor的基本执行流程。