Directorio de artículos
Pregunta 1: Cuándo activar MaximumPoolSize
En el blog anterior , se mencionó la comprensión de los siete parámetros del grupo de subprocesos de JUC :
1. Cuando
corePoolSize 核心数
se alcanza el límite superior, los datos de la nueva operación en este momento se guardarán en la cola.
2, cuando队列
la memoria estaba a tiempo completo, se abrirá unamaximumPoolSize - corePoolSize
parte.
Pregunta 2: ¿Por qué esperar hasta que la cola esté llena antes de activar maximumPoolSize?
Antes de explicar este problema, debemos comprender dos conceptos: 提交优先级
y 执行优先级
.
提交优先级:
En
线程池
,
1. La operación de procesamiento se entregará primero alcorePoolSize
procesamiento de datos.
2. SicorePoolSize
está lleno, dará prioridad al队列
almacenamiento temporal.
Como sigue:
执行优先级:
1. Intente entregarlo primero
core
para el procesamiento de datos.
2. Si es asícore 被占用
, se entregará a la ventana de procesamiento restante para su procesamiento.
3. Si lamax
ventana de procesamiento está completamente ocupada, los datos se almacenarán temporalmente en la cola.
De la siguiente manera:
Ver descripción del código fuente:
Se llama a cualquier operación que obtenga un elemento de operación del grupo de subprocesos
execute(Runnable command)
.
Parte fuente:
// 用来标记线程池状态(高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;
}