线程池源码剖析
1. 手写一个简单线程池
目前业界线程池的设计,普遍采用的都是生产者——消费者模型,线程的使用方是生产者,而线程池就是一个消费者;
下面来设计一个简易的线程池MythreadPool,它的设计原理跟我们的ThreadPoolExecutor的设计思想是一致的;
class MythreadPool {
//用阻塞队列来保存任务
BlockingQueue<Runnable> workQueue;
List<WorkThread> workers = new ArrayList<>();
public MythreadPool(int poolSize, BlockingQueue<Runnable> blockingQueue) {
this.workQueue = blockingQueue;
for(int i=0; i<poolSize; i++) {
WorkThread workThread = new WorkThread();
workThread.start();
workers.add(workThread);
}
}
//提交任务
public void excute(Runnable runnable) {
workQueue.add(runnable);
}
class WorkThread extends Thread {
@Override
public void run() {
//这里是个死循环,所以工作的线程不会结束,会在这里一直等待从阻塞队列中获取任务;
while (true) {
try {
Runnable task = workQueue.take();
task.run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class Test2 {
public static void main(String[] args) {
MythreadPool mythreadPool = new MythreadPool(3, new ArrayBlockingQueue<>(3));
mythreadPool.excute(new Runnable() {
@Override
public void run() {
System.out.println("hello my threadPool!!!!");
}
});
}
}
输出:
hello my threadPool!!!
由于没有实现关闭线程池的方法,上述输出是不会结束的,需强制关闭;
2. 线程池体系架构
Executor是位于juc包下的一个接口;
可以看到顶层是Executor接口,这个接口就一个方法:
-
void execute(Runnable command);
接下来是ExecutorService接口,这个接口作用是:
- 提供了线程池生命周期的一些管理方法;
- 接下来是AbstractExecutorService,这个抽象类则是具体实现了上面ExecutorService接口中的那些方法;
最下面的就是我们常用的ThreadPoolExecutor,下面具体进行讲解;
2. ThreadPoolExcutor源码解读
1. 工作状态概述
ThradPoolExecutor提供了对线程生命周期的控制,规定线程池有如下五种状态:
- RUNNING(运行)
- 能够接受新的任务,也可以处理阻塞队列里面的任务;
- SHUTDOWN(待关闭)
- 不能够接受新的任务,继续处理阻塞队列里的任务;
- STOP(停止)
- 不能够接受新的任务,也不会处理阻塞队列里的任务,并且会中断正在处理的任务;
- TIDYING(整理)
- 所有的任务已经停止,ctl记录的工作线程数为0,线程池会变为TIDYING状态,此状态线程池会执行钩子方法terminated();
- TERMINATED(终止)
- 完全终止,且已经释放了所有的资源;
根据源码注释,使用ctl的高三位来表示上面五种状态,低29位来表示线程池中的工作线程数;
所谓的工作线程数,就是已经被允许start并且不允许被停止的线程;
//ctl是一个原子数,线程安全的(CAS),初始值的设定代表RUNNING状态和工作线程数为0;
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
//COUNT_BITS即为32-3,为29;
private static final int COUNT_BITS = Integer.SIZE - 3;
//表示工作线程的最大数,2^29 - 1;
//即:00011111 11111111 11111111 11111111
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
//获取线程池状态
//c 来与上CAPACITY取反,即与上:11100000 00000000 00000000 0000000,即取得c的前三位;
private static int runStateOf(int c) { return c & ~CAPACITY; }
//获取工作线程数
//c 来与上CAPACITY,即与上:00011111 11111111 11111111 11111111,即获得c的第27位;
private static int workerCountOf(int c) { return c & CAPACITY; }
//将状态与线程数进行或运算,刚好就组成了ctl; 因为rs的低27位全为零,wc的高3位全为0,而0与任意数
//进行或运算的结果就是那个任意数;
private static int ctlOf(int rs, int wc) { return rs | wc; }
2. 工作状态的转换
- (1):RUNNING 转换为 SHUTDOWN :在调用shutdown()方法时;
- (2):RUNNING或SHUTDOWN 转换为 STOP:调用shutdownNow()方法时;
- (3):SHUTDOWN 转化为 TIDYING:当阻塞队列和工作线程数都为0时;
- (4):STOP 转化为 TIDYING:当工作线程数为0时;
- (5):TIDYING 转化为 TERMINATED:当terminated()钩子方法完成时;