线程池能够帮助我们提高系统资源利用效率,并简化线程管理。通过并发包下的Executors(不是Executor)可以方便的创建如下几类线程池。分别为:
下面来分析一下ThreadPoolExecutor是如何实现线程池的。首先看看线程池框架图:
线程池框架
应用与线程池的交互和线程池的内部工作过程如下图所示:
应用与线程池的交互和线程池的内部工作过程
其中有几个重要的概念:
理解了上面的几个概念,再看ThreadPoolExecutor的构造方法就能够很容易的理解各参数的含义了,源码截图如下:
ThreadPoolExecutor构造方法
execute方法的源码如下:
public void execute(Runnable command) {
//验证传入参数的合法性
if (command == null)
throw new NullPointerException();
// 检查工作线程数目,低于 corePoolSize 则添加线程(这里的线程给Worker进行包装)
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
//线程没有被shutdown,则将command加入到任务队列中
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);
}
// 尝试添加一个 worker,如果失败以为着已经饱和或者被shutdown了
else if (!addWorker(command, false))
reject(command);
}
线程状态流转图如下所示:
线程状态流转图