【Android 异步操作】线程池 ( 线程池 reject 拒绝任务 | 线程池 addWorker 添加任务 )
文章目录
在上一篇博客 【Android 异步操作】线程池 ( 线程池 execute 方法源码解析 ) 中 , 讲解 线程池 ThreadPoolExecutor 的 execute 方法时 , 有两个重要的核心方法 ;
两个核心的操作 :
- 添加任务 : addWorker(command, true) , 第二个参数为 true 是添加核心线程任务 , 第二个参数为 false 是添加非核心线程任务 ;
- 拒绝任务 : reject(command)
本博客中研究 拒绝任务 reject 方法的细节 ;
一、线程池 reject 拒绝任务
在 ThreadPoolExecutor 线程池中 , void reject(Runnable command) 方法 , 主要是调用了 RejectedExecutionHandler handler 的 rejectedExecution 方法 ;
该 handler 可以在如下 构造函数中传入 , 如下构造函数中的最后一个参数 ;
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
部分相关代码示例 :
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 方法 , 当 线程池任务队列饱和 , 或者 没有空闲线程 时 , 线程池被关闭 时 , 导致线程池的任务队列无法接受该任务时 , 会调用该方法
/**
* 处理添加任务失败情况的 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 ) , 并执行第一个初始任务 ,
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;
}
}
相关文章
- android 空间分享到朋友圈,Android开发之微信分享到好友,朋友圈
- Android SDK 安装及环境配置教程
- android退出app代码,Android应用退出代码各种方式
- Windows Subsystem for Android 安装<简化向>[通俗易懂]
- android 安装p12证书,如何在Android中使用p12证书(客户端证书)
- android sdk安装过程,图文详解Android 3.0 SDK安装教程
- android 验证码短信验证码,Android短信验证码倒计时验证的2种常用方式
- android短信验证码方案,Android开发之属于你的短信验证码(一)
- 深入理解Android图形系统
- android登录注册跳转的代码_Android开发代码
- android activitymanager 系统api_Android view
- android线程通信的几种方式_java多线程的实现方式
- Android 渐变圆环,圆形进度条效果实现
- 【技术分享】Android渗透测试
- 【Android 应用开发】自定义View 和 ViewGroup
- 【Android 高性能音频】AAudio 缓冲区控制 ( XRun | 欠载 UnderRun | 超限 OverRun | 获取缓冲区大小 | 设置缓冲区大小 )
- 【Android 异步操作】线程池 ( 线程池简介 | 线程池初始化方法 | 线程池种类 | AsyncTask 使用线程池示例 )
- 【错误记录】Android Studio 编译报错 ( Could not find com.android.tools.build:gradle:4.2.1. )
- 【Android 逆向】x86 汇编 ( call 子函数调用指令 | jmp 跳转指令 | lea 加载指令 | mov 数据传送指令 )
- 【Android 逆向】Android 逆向通用工具开发 ( Android 端远程命令工具 | Android 端可执行程序的 main 函数操作 | TCP 协议服务器建立 | 接收客户端数据 )
- 【错误记录】Android Gradle 配置报错 ( gradle.properties 配置到 BuildConfig 中需要注意类型转换 | 位置: 类 BuildConfig )
- Android 线程池的类型、区别以及为何要用线程池详解手机开发
- android Universal Image Loader for Android 说明文档 (1)详解手机开发
- Android 四种常见的线程池详解手机开发
- 使用Android新式LruCache缓存图片,基于线程池异步加载图片详解编程语言
- Android系统与Linux之间的联系(android和linux)
- NCR 发布基于 Android/Linux 的 ATM 终端机
- android开发中常用的Eclipse快捷键详细整理
- android使用handlerthread创建线程示例
- android错误aapt.exe已停止工作的解决方法
- Android应用开发之代码混淆