Article Directory
Question 1: When to turn on maximumPoolSize
In the previous blog, the understanding of the seven parameters of the thread pool of JUC , it was mentioned:
1. When the
corePoolSize 核心数
upper limit is reached, the new operation data at this time will be saved in the queue.
2, when队列
the memory was full time, will openmaximumPoolSize - corePoolSize
part.
Question 2: Why wait until the queue is full before turning on maximumPoolSize
Before explaining this problem, we need to understand two concepts: 提交优先级
and 执行优先级
.
提交优先级:
In
线程池
,
1. The processing operation will be handed overcorePoolSize
to the data processing first .
2. If itcorePoolSize
is full, it will give priority to队列
temporary storage.
As follows:
执行优先级:
1. Try to hand it over
core
for data processing first .
2. If it iscore 被占用
, it will be handed over to the remaining processing window for processing.
3. If themax
processing window is all occupied, the data will be temporarily stored in the queue.
As shown below:
View source code description:
Any operation that gets an operation item from the thread pool is called
execute(Runnable command)
.
Source part:
// 用来标记线程池状态(高3位),线程个数(低29位)
// 默认 RUNNING 状态,线程个数为0
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
// 用来获取线程个数
private static final int COUNT_BITS = Integer.SIZE - 3;
// 用于获取线程最大个数
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// 各项状态参数信息
// 正在运行
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;
// Packing and unpacking ctl
private static int runStateOf(int c) {
return c & ~CAPACITY; }
private static int workerCountOf(int c) {
return c & CAPACITY; }
private static int ctlOf(int rs, int wc) {
return rs | wc; }
public void execute(Runnable command) {
// 判断 runnable 对象体是否存在
if (command == null)
throw new NullPointerException();
// 这个 c 就是当前的线程池状态值 默认为 ctlOf(RUNNING, 0) 运行中且线程个数为0
// ctl 记录runstate 和 workercount
int c = ctl.get();
// workerCountOf(c) 取出 低29 位数据值,即活动线程数
// 如果活动线程数 小于 core(核心) 线程数
// 则会新建线程,放置于池中,并将runnable任务加入该线程
if (workerCountOf(c) < corePoolSize) {
// 如果 创建 “核心线程数据体” 成功 则直接退出
if (addWorker(command, true))
return;
// 创建核心线程失败,重新获取 活动线程状态
c = ctl.get();
}
// 将 重新获取到线程池的状态值,进行判断
// 如果线程池的状态是 “正在运行”,并且将这个Runnable任务放入队列成功!
if (isRunning(c) && workQueue.offer(command)) {
// 重新获取 线程状态值
int recheck = ctl.get();
// 这里是安全校验
// 如果监测到线程池为“非运行状态”,则需要将上面workQueue.offer(command)成功的数据移除
if (! isRunning(recheck) && remove(command))
// 告知拒绝策略,对该任务进行处理
reject(command);
// 根据线程的状态值信息
// 采取workerCountOf(recheck) 取出 低29 位数据值,即活动线程数
// 如果活动线程数没了
else if (workerCountOf(recheck) == 0)
// null 表示在线程池创建新的线程,但不启动
// boolean ,true表示是core类型,false为maxpoolsize
// 创建某个时候会执行的commond
addWorker(null, false);
}
// 1、如果线程池状态不是RUNNING状态
// 2、如果线程池是RUNNING状态,但是队列塞满了
// 则进行下列判断
// 如果将执行任务添加“备用窗口”失败(开启最大maxpool去执行),
// 但是此时添加执行失败(max全被占用)
else if (!addWorker(command, false))
// 则采取拒绝策略,拒绝掉该Runnable执行体
reject(command);
}
private static boolean isRunning(int c) {
return c < SHUTDOWN;
}