文章目录
- 一、线程池 reject 拒绝任务
- 二、线程池 addWorker 添加任务
在上一篇博客 【Android 异步操作】线程池 ( 线程池 execute 方法源码解析 ) 中 , 讲解 线程池 ThreadPoolExecutor 的 execute 方法时 , 有两个重要的核心方法 ;
两个核心的操作 :
- 添加任务 : addWorker(command, true) , 第二个参数为 true 是添加核心线程任务 , 第二个参数为 false 是添加非核心线程任务 ;
- 拒绝任务 : reject(command)
本博客中研究 拒绝任务 reject 方法的细节 ;
一、线程池 reject 拒绝任务
在 ThreadPoolExecutor 线程池中 , void reject(Runnable command) 方法 , 主要是调用了 RejectedExecutionHandler handler 的 rejectedExecution 方法 ;
该 handler 可以在如下 构造函数中传入 , 如下构造函数中的最后一个参数 ;
代码语言:javascript复制 public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
部分相关代码示例 :
代码语言:javascript复制public class ThreadPoolExecutor extends AbstractExecutorService {
/**
* 当线程池任务饱和 , 或线程池关闭 , 使用该 Handler 处理拒绝任务异常情况 ;
*/
private volatile RejectedExecutionHandler handler;
/**
* 在该构造函数中 , 可以传入 Handler ;
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
/**
* 拒绝执行给定命令的处理
*/
final void reject(Runnable command) {
handler.rejectedExecution(command, this);
}
}
自定义 RejectedExecutionHandler 处理拒绝任务的情况 ;
实现 rejectedExecution 方法 , 当 线程池任务队列饱和 , 或者 没有空闲线程 时 , 线程池被关闭 时 , 导致线程池的任务队列无法接受该任务时 , 会调用该方法
代码语言:javascript复制/**
* 处理添加任务失败情况的 handler
* 用户可以自定义该接口
*/
public interface RejectedExecutionHandler {
/**
*
* 无法接受任务时执行该方法 ;
* 当线程池任务队列饱和 , 或者没有空闲线程时 , 线程池被关闭时 , 会调用该方法
*
* 该方法可能会触发 RejectedExecutionException 异常 , 用户需要捕获并处理该异常
*
* @param r 被拒绝的任务
* @param executor 尝试执行该任务的执行者
* @throws RejectedExecutionException 如果没有补救方法, 抛出该异常
*/
void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}
二、线程池 addWorker 添加任务
检查一个新的工作者 ( Worker ) 是否可以被添加 , 根据当前的 线程池状态 , 和 给定的核心线程数 , 最大线程数 等判定 ;
如果可以添加 , 那么先 调整 工作者 ( Worker ) 的个数 , 然后 创建新的 工作者 ( Worker ) , 并 将参数中的 Runnable firstTask 设置为第一个任务 ;
如果线程池停止或关闭 , 返回 false ;
如果线程创建失败 , 不管是线程工厂返回空 , 还是出现 OOM , 直接退出 ;
如果当前的 线程个数少于 核心线程数 , 或者当前的 任务数已满 , 则必须创建 工作者 ( Worker ) , 并执行第一个初始任务 ,
代码语言:javascript复制public class ThreadPoolExecutor extends AbstractExecutorService {
/**
* 检查一个新的工作者是否可以被添加 , 根据当前的线程池状态 , 和给定的核心线程数 , 最大线程数等判定 ;
* 如果可以添加 , 那么先调整 工作者 ( Worker ) 的个数 , 然后创建新的 工作者 ( Worker ) ,
* 并将参数中的 Runnable firstTask 设置为第一个任务 ;
* 如果线程池停止或关闭 , 返回 false ;
* 如果线程创建失败 , 不管是线程工厂返回空 , 还是出现 OOM , 直接退出 ;
*
* 第一个运行的任务 ;
* 如果当前的线程个数少于 核心线程数 , 或者当前的任务数已满 ,
* 必须创建 工作者 ( Worker ) , 并执行第一个初始任务 ,
*
* @param core 如果设置为 true , 必须使用核心线程绑定
* @return true if successful
*/
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
// 死循环
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// 查看队列是否为空
// 查看线程池是否 SHUTDOWN
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
// 查看线程池的线程个数 , 与 核心线程数, 最大线程数 进行各种对比
// 获取现在的线程池情况
for (;;) {
int wc = workerCountOf(c);
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
// 如果没有达到最大线程数 , 允许添加
if (compareAndIncrementWorkerCount(c)) // 该行代码只是将计数器 1
break retry;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
// 下面是添加一个线程的逻辑
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
// 创建工作者 , 并将任务设置给该工作者
w = new Worker(firstTask);
// 线程是从工作者中取出的 , 该线程是在 Worker 构造函数中使用线程工厂创建的
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
// 将工作者设置给 工作者集合
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
// 如果添加成功 , 就会启动 Worker 中的线程
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
}