1 ThreadPoolExecutor部分解析
Java构造线程的方式
- 继承Thread
- 实现Runnable
- 实现Callable
- 线程池方法(Java提供了构建线程池的方法)
- Java提供的Executors可以创建(规范中不允许使用这种方式创建线程池)
线程池的参数
public ThreadPoolExecutor(
int corePoolSize, // 核心线程数
int maximumPoolSize, // 最大线程数
long keepAliveTime, // 最大空闲时间
TimeUnit unit, // 时间单位
BlockingQueue<Runnable> workQueue, // 阻塞队列
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler // 拒绝策略
){
}
线程池的执行流程
饭店(线程池)
厨子(线程)
(这时来了好多顾客) 我们先是人多先排队(阻塞队列)
(当每天都来很多人我们想到)招厨子(创建最大线程数)
今日客满 (拒绝 - 拒绝策略)
线程池属性标识
// 1. 声明当前线程的状态 2.声明线程池中的线程数
// 高3位:线程池状态 低29位 : 线程池中的线程个数
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3; // 值为29
private static final int COUNT_MASK = (1 << COUNT_BITS) - 1; // 通过位运算得出最大容量
// runState is stored in the high-order bits 线程池状态 高3位
private static final int RUNNING = -1 << COUNT_BITS; // 111 代表正常接收任务
private static final int SHUTDOWN = 0 << COUNT_BITS; // 000 不接收新任务,但是内部还会处理阻塞队列中的任务,正在进行的任务也正常处理
private static final int STOP = 1 << COUNT_BITS; // 001 不接收新任务,也不去处理阻塞队列中的任务,同时会中断正在执行的任务
private static final int TIDYING = 2 << COUNT_BITS; // 010 过渡的状态,代表当前线程池即将Game Over
private static final int TERMINATED = 3 << COUNT_BITS; // 011 真正的结束了
// Packing and unpacking ctl
private static int runStateOf(int c) { return c & ~COUNT_MASK; } // 得到线程池的状态
private static int workerCountOf(int c) { return c & COUNT_MASK; } // 得到现在线程池的线程数量
private static int ctlOf(int rs, int wc) { return rs | wc; }
线程池的execute方法执行
// execute方法
if (command == null)
throw new NullPointerException();
// 拿到32位的int数值
int c = ctl.get();
// 获取 工作线程数 < 核心线程数
if (workerCountOf(c) < corePoolSize) {
// 进入if 代表可以创建核心线程数
if (addWorker(command, true))
return;
// 如果没进入if 代表创建核心线程数失败,重新获取 ctl
c = ctl.get();
}
// 判断线程池是不是RUNNING,将任务添加到阻塞队列中
if (isRunning(c) && workQueue.offer(command)) {
// 再次获得 ctl
int recheck = ctl.get();
// 再次判断是否是RUNNING , 如果不是RUNNING 移除任务
if (! isRunning(recheck) && remove(command))
reject(command); // 拒绝策略
// 如果线程池处于RUNNING状态,BUT工作线程为0
else if (workerCountOf(recheck) == 0)
// 阻塞队列有任务,但是没有工作线程,添加一个任务为空的工作线程处理阻塞队列中的任务
addWorker(null, false);
}
// 创建非核心线程,处理任务
else if (!addWorker(command, false))
reject(command); // 拒绝策略
}
通过上述源码,掌握了线程池的执行流程.