参数的理解:
核心和最大池大小 Core and maximum pool sizes
ThreadPoolExecutor将根据corePoolSize 和 maximumPoolSize 设置的边界自动调整线程池大小,在方法execute(Runnable)中提交新任务时,如果运行的线程数少于corePoolSize, 即使其他工作线程处于空闲状态,也会创建一个新线程来处理请求。 如果运行的线程数少于最大池大小,并且在队列已满时 则将创建一个新线程处理请求。通过将corePoolSize和maximumPoolSize设置为相同值,可以创建一个固定大小的线程池。 通过将 maximumPoolSize 设置为基本上无界的值,如Integer.MAX_VALUE 就是允许线程池容纳任意数量的并发任务。核心和最大池大小可以在构建时设置,也可以使用setCorePoolSize 和 setMaximumPoolSize 动态更改。
// 对于 corePoolSize (核心线程数 来说)
if (池中已经创建的线程 < corePoolSize){
立即创建一个线程来处理请求。
}
// 对于 maximumPoolSize (最大池中线程数大小 来说)
if ( (运行的线程数 < maximumPoolSize ) && workQueue.isEmpty()){
立即创建一个线程来处理请求。
}
corePoolSize:池中要保留的线程数,即使它们处于空闲状态。
maximumPoolSize:池中允许的最大线程数
keepAliveTime:当线程数大于核心时,这是多余空闲线程在终止前等待新任务的最长时间。
unit:keepAliveTime参数的时间单位
workQueue:在执行任务之前用于保存任务的队列。此队列将仅保存execute方法提交的Runnable任务。
threadFactory:执行器创建新的线程时使用的工厂
拒绝策略:当执行因达到线程边界 和 队列容量时 使用的策略,如果任务阻塞队列已满且线程池中的线程数等于maximumPoolSize,说明线程池此时处于饱和状态,应该执行一种拒绝策略来处理新提交的任务。
4种拒绝策略:
1.默认的拒绝策略 new ThreadPoolExecutor.AbortPolicy();
直接抛出异常:抛出RejectedExecutionException
2.由提交任务的线程处理该任务: new ThreadPoolExecutor.CallerRunsPolicy();
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
3.不执行任务,也不抛出异常,直接丢弃:new ThreadPoolExecutor.DiscardPolicy()
方法里面什么也没有实现:
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { }
4.丢弃队列中最老的任务,然后尝试再次提交任务:
new ThreadPoolExecutor.DiscardOldestPolicy()
方法的实现:
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
5. 自定义拒绝策略 实现 RejectedExecutionHandler 接口中的 rejectedExecution 方法
void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
execute方法的流程:
public static void main(String[] args) {
// 创建一个固定大小的线程池
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
ThreadPoolExecutor executor = new ThreadPoolExecutor(
1, // 核心线程数
2, // 最大线程数
0L, // 存活时间
TimeUnit.MILLISECONDS,
workQueue,
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);
// 提交任务
for (int i = 0; i < 10; i++) {
executor.execute(() -> {
System.out.println("Task executed on thread: " + Thread.currentThread().getName());
});
}
// 关闭线程池
executor.shutdown();
}
用的是默认的线程工厂 Executors.defaultThreadFactory() 线程池的控制状态ctl是一个原子整数,它包含了两个概念字段 workerCount:表示线程的有效数量 runState:表示是否正在运行、关闭等 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); private static int ctlOf(int rs, int wc) { return rs | wc; }
//workerCount 线程的数量(2^29)-1(约5亿)个线程 private static final int COUNT_BITS = Integer.SIZE - 3; private static final int COUNT_MASK = (1 << COUNT_BITS) - 1; COUNT_MASK 二进制是:00011111111111111111111111111111 COUNT_MASK 值是:536870911 // runState 存储在高位 private static final int RUNNING = -1 << COUNT_BITS; -1 的二进制数:11111111111111111111111111111111 左移动29的二进制数:11100000000000000000000000000000 RUNNIN 的 值是: -536870912 中间记录一下负数 左移动的 插曲: 负数:取最高位有值的数,中间有间隔的数 减去间隔的数字。取反 例如:-10 源码:0000 1010 反码:1111 0101 补码:1111 0110 左移动4位 -10 int 类型的二进制:1111 1111 1111 1111 1111 1111 0110 0000 取最高位的值是:从右边数第9位是:256 减去间隔的值右边数6位和7位,他们的值是 64+32=96 256 - 96 = 160 private static final int SHUTDOWN = 0 << COUNT_BITS; 0 的二进制数:0 左移动29的二进制数:0 SHUTDOWN 的 值是:0 private static final int STOP = 1 << COUNT_BITS; 1 的二进制数:00000000000000000000000000000001 左移动29的二进制数:00100000000000000000000000000000 STOP 的 值是:536870912 private static final int TIDYING = 2 << COUNT_BITS; 2 的二进制数:00000000000000000000000000000010 左移动29的二进制数:01000000000000000000000000000000 TIDYING 的 值是:1073741824 private static final int TERMINATED = 3 << COUNT_BITS; 3 的二进制数:00000000000000000000000000000011 左移动29的二进制数:01100000000000000000000000000000 TERMINATED的值是:
进入 execute 方法:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
/**
* 分为3个步骤:
*
* 1.如果运行的线程数少于corePoolSize,请尝试使用给定的任务作为第一个任务启动一个新线程。
* 对addWorker的调用会自动检查runState和workerCount,
* 从而通过返回false来防止在不应该添加线程的情况下添加错误警报
*
* 2.如果一个任务可以成功排队,那么我们仍然需要仔细检查是否应该添加一个线程(因为自上次检查以来,现有的线程已经死亡),
* 或者池是否在进入此方法后关闭。因此,我们重新检查状态,并在必要时回滚查询,如果没有,则停止或启动新线程。
*
* 3.如果我们无法对任务进行排队,那么我们会尝试添加一个新线程。
* 如果它失败了,我们知道我们被关闭或饱和了,因此拒绝了这项任务。
*
*/
/**
* 第一次进来
* ctl.get() 获取的值是 -536870912
* 初始化的时候 RUNNING 是 :11100000000000000000000000000000
* private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
* 经过 | 后 结果不变
* private static int ctlOf(int rs, int wc) { return rs | wc; }
* 第二次进来
* ctl.get() 获取的值是 -536870911 (在第一次的时候已经 进行了 + 1)
*/
int c = ctl.get();
/**
* 第一次进来
* private static int workerCountOf(int c) { return c & COUNT_MASK; }
* c 传过来的值是 -536870912 & COUNT_MASK
* COUNT_MASK 的值是:536870911
* c的二进制数: 11100000000000000000000000000000
* &
* COUNT_MASK: 00011111111111111111111111111111
* 是 0 corePoolSize 是 1 结果是 true
* 第二次进来
* private static int workerCountOf(int c) { return c & COUNT_MASK; }
* c 传过来的值是 -536870911 & COUNT_MASK
* COUNT_MASK 的值是:536870911
* c的二进制数: 11100000000000000000000000000001
* &
* COUNT_MASK: 00011111111111111111111111111111
* 是 1 corePoolSize 是 1 结果是 false
*/
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
// 因为我核心数的大小设置的是 1 ,所以第二次就进到这里
// private static boolean isRunning(int c) { return c < SHUTDOWN; }
// c 是 -536870911 < SHUTDOWN 是 0 结果是true
// 然后判断队列是否可以插入数据 workQueue.offer(command) 没有给队列设置大小,可以插入进来
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
// 上面已经验证, 这里取反返回false
if (! isRunning(recheck) && remove(command))
reject(command);
// private static int workerCountOf(int c) { return c & COUNT_MASK; }
// COUNT_MASK的二进制是: 11111111111111111111111111111
// c的二进制是: 11100000000000000000000000000001
// 返回 1 结果为 false 里面没有处理任务 直接返回了 , 全部添加到了队列
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//将 队列设置为1 后 直接走到拒绝策略
else if (!addWorker(command, false))
reject(command);
}
addWorker(Runnable firstTask, boolean core)方法:
/**
* 检查是否可以根据当前线程池状态和给定的绑定(核心或最大值)添加新的worker。
* 如果可以,则创建并启动一个新worker,将firstTask作为其第一个任务运行。
* 如果线程池已停止或符合关闭条件,则此方法返回false。如果线程工厂在被询问时不能创建线程,它也会返回false。
* 如果线程创建失败,无论是由于线程工厂返回null,还是由于异常(通常是thread.start()中的OutOfMemoryError),
* 我们都会彻底回滚。
* @param firstTask 线程
* @param core true 当前的线程数 < core线程数
* @return
*/
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
// c 是 -536870912
for (int c = ctl.get();;) {
// 运行状态的检查
// private static boolean runStateAtLeast(int c, int s) { return c >= s; }
//
// private static final int SHUTDOWN = 0 << COUNT_BITS;
// private static final int STOP = 1 << COUNT_BITS;
// SHUTDOWN 是 0 STOP 是 536870912
// -536870912 >= 0 && -536870912 > 536870912 返回 false
if (runStateAtLeast(c, SHUTDOWN)
&& (runStateAtLeast(c, STOP)
|| firstTask != null
|| workQueue.isEmpty()))
return false;
for (;;) {
// private static int workerCountOf(int c) { return c & COUNT_MASK; }
// c 的 二进制是: 11100000000000000000000000000000
// COUNT_MASK是: 00011111111111111111111111111111
// 没有线程在工作 返回 0
// 0 >= 1
if (workerCountOf(c)
>= ((core ? corePoolSize : maximumPoolSize) & COUNT_MASK))
return false;
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get(); // Re-read ctl
if (runStateAtLeast(c, SHUTDOWN))
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
boolean workerStarted = false;
boolean workerAdded = false;
ThreadPoolExecutor.Worker w = null;
try {
//利用线程的工厂创建线程
w = new ThreadPoolExecutor.Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
// 上锁
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// 拿到锁后重新检查。
// 如果ThreadFactory失败或在获得锁之前关闭,则退出。
// 前边已经原子 进行了 加 1 获取的值是:-536870911
int c = ctl.get();
// private static boolean isRunning(int c) { return c < SHUTDOWN; }
// SHUTDOWN 是 0
// 结果返回true
if (isRunning(c) ||
(runStateLessThan(c, STOP) && firstTask == null)) {
// 新创建的线程 没有执行之前的状态都是 new
if (t.getState() != Thread.State.NEW)
throw new IllegalThreadStateException();
workers.add(w);
workerAdded = true;
int s = workers.size();
// 跟踪已达到的最大池大小。仅在mainLock下访问
if (s > largestPoolSize)
largestPoolSize = s;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
辅助方法:
// 原子修改 这个 线程池状态 工作线程 +1
private boolean compareAndIncrementWorkerCount(int expect) {
return ctl.compareAndSet(expect, expect + 1);
}
//创建一个线程
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
根据拒绝的策略,最后由main方法 执行拒绝后的任务