文章目录

  • 一、线程池 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))   // 该行代码只是将计数器 +1break retry;c = ctl.get();  // Re-read ctlif (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 startablethrow 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 异步操作】线程池 ( 线程池 reject 拒绝任务 | 线程池 addWorker 添加任务 )相关推荐

  1. 【Android 异步操作】手写 Handler ( Message 消息 | ThreadLocal 线程本地变量 | Looper 中的消息队列 MessageQueue )

    文章目录 一.Message 消息 二.ThreadLocal 线程本地变量 三.Looper 中的消息队列 MessageQueue 一.Message 消息 模仿 Android 中的 Messa ...

  2. 【Android 异步操作】线程池 ( 线程池使用示例 | 自定义线程池使用流程 | 自定义任务拒绝处理策略 | 完整代码示例 )

    文章目录 一.自定义线程池使用流程 二.自定义任务拒绝处理策略 三.完整代码示例 在博客 [Android 异步操作]线程池 ( 线程池简介 | 线程池初始化方法 | 线程池种类 | AsyncTas ...

  3. 【Android 异步操作】线程池 ( Worker 简介 | 线程池中的工作流程 runWorker | 从线程池任务队列中获取任务 getTask )

    文章目录 一.线程池中的 Worker ( 工作者 ) 二.线程池中的工作流程 runWorker 三.线程池任务队列中获取任务 getTask 在博客 [Android 异步操作]线程池 ( 线程池 ...

  4. 【Android 异步操作】线程池 ( 线程池 execute 方法源码解析 )

    文章目录 一.线程池 execute 方法源码解析 二.线程池 execute 方法完整源码及注释 一.线程池 execute 方法源码解析 进入 ThreadPoolExecutor 中 , 查看线 ...

  5. 【Android 异步操作】线程池 ( 线程池作用 | 线程池种类 | 线程池工作机制 | 线程池任务调度源码解析 )

    文章目录 一.线程池作用 二.线程池种类 三.线程池工作机制 四.线程池任务调度源码解析 一.线程池作用 线程池作用 : ① 避免创建线程 : 避免每次使用线程时 , 都需要 创建线程对象 ; ② 统 ...

  6. 【Android 异步操作】线程池 ( 线程池简介 | 线程池初始化方法 | 线程池种类 | AsyncTask 使用线程池示例 )

    文章目录 一.线程池简介 二.线程池初始化方法简介 三.线程池使用示例 一.线程池简介 线程池一般是实现了 ExecutorService 接口的类 , 一般使用 ThreadPoolExecutor ...

  7. 《Java线程池》:任务拒绝策略

    <Java线程池>:任务拒绝策略 转载:https://blog.csdn.net/u010412719/article/details/52132613 在没有分析线程池原理之前先来分析 ...

  8. Java多线程学习七:线程池的 4 种拒绝策略和 6 种常见的线程池

    以便在必要的时候按照我们的策略来拒绝任务,那么拒绝任务的时机是什么呢?线程池会在以下两种情况下会拒绝新提交的任务. 第一种情况是当我们调用 shutdown 等方法关闭线程池后,即便此时可能线程池内部 ...

  9. Java线程与Android线程,Android线程篇(三):深入理解Java线程池(一)

    上篇文章我们讲解了Java的四种线程池,我们知道如何去使用四种线程池,以及在合适的情况下使用合适的线程池,常言道,不懂原理的厨师不是好的程序员,所以本篇文章,就带大家一起去探寻Java线程池的秘密. ...

最新文章

  1. 关于xib里面的NSLayoutConstraint的multiplier修改
  2. weblogic集群的资料
  3. 逐浪CMS4.6精彩预告之三:全新会员中心炫目登场
  4. ubnutu18.10拔除硬盘后进行recovery mode
  5. 7个使用JavaScript构建数据可视化的实用工具库,希望你能喜欢
  6. JavaScript学习(五十五)—组合继承
  7. 数码相机与计算机接口,数码相机怎么连接电脑
  8. scala练习100道解析
  9. unbtun python tab补全
  10. [Luogu P3704] [BZOJ 4816] [SDOI2017]数字表格
  11. 数据科学家的修行之路---基本功
  12. 20165309 实验四 Android程序设计
  13. html新年礼物,特别的新年礼物 特殊的新年礼物
  14. 计算机学院早操规定,计算机学院早操动员大会顺利召开
  15. 网络流量一对多镜像配置
  16. C# AssemblyInfo.cs文件的作用
  17. 虎符CTF 2022 mva
  18. pycharm Failed to connect to github.com port 443: Timed out
  19. 19届毕业生在字节跳动工作的真实体验!
  20. 「网络暴力」离我们到底有多远?

热门文章

  1. 浏览器根据什么来判定脚本失控?
  2. 从宏观经济状况看目前股市
  3. VBA 的编写与执行
  4. Qt 2D绘图之二:抗锯齿渲染和坐标系统
  5. 20175208『Java程序设计』课程 结对编程练习_四则运算
  6. Bootstrap UI 编辑器
  7. C++:不用申请变量交换两个变量的值
  8. ICA(独立成分分析)笔记
  9. MongoDB之python简单交互(三)
  10. Qt实现截屏并保存(转载)