【Android 异步操作】线程池 ( 线程池 reject 拒绝任务 | 线程池 addWorker 添加任务 )

举报
韩曙亮 发表于 2022/01/10 23:13:25 2022/01/10
【摘要】 文章目录 一、线程池 reject 拒绝任务二、线程池 addWorker 添加任务 在上一篇博客 【Android 异步操作】线程池 ( 线程池 execute 方法源码解析 ) ...



在上一篇博客 【Android 异步操作】线程池 ( 线程池 execute 方法源码解析 ) 中 , 讲解 线程池 ThreadPoolExecutorexecute 方法时 , 有两个重要的核心方法 ;

两个核心的操作 :

  • 添加任务 : addWorker(command, true) , 第二个参数为 true 是添加核心线程任务 , 第二个参数为 false 是添加非核心线程任务 ;
  • 拒绝任务 : reject(command)

本博客中研究 拒绝任务 reject 方法的细节 ;





一、线程池 reject 拒绝任务



ThreadPoolExecutor 线程池中 , void reject(Runnable command) 方法 , 主要是调用了 RejectedExecutionHandler handlerrejectedExecution 方法 ;

该 handler 可以在如下 构造函数中传入 , 如下构造函数中的最后一个参数 ;

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

部分相关代码示例 :

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);
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39


自定义 RejectedExecutionHandler 处理拒绝任务的情况 ;

实现 rejectedExecution 方法 , 当 线程池任务队列饱和 , 或者 没有空闲线程 时 , 线程池被关闭 时 , 导致线程池的任务队列无法接受该任务时 , 会调用该方法


/**
 * 处理添加任务失败情况的 handler 
 * 用户可以自定义该接口 
 */
public interface RejectedExecutionHandler {

    /**
     * 
     * 无法接受任务时执行该方法 ;
     * 当线程池任务队列饱和 , 或者没有空闲线程时 , 线程池被关闭时 , 会调用该方法
     *
     * 该方法可能会触发 RejectedExecutionException 异常 , 用户需要捕获并处理该异常
     *
     * @param r 被拒绝的任务
     * @param executor 尝试执行该任务的执行者
     * @throws RejectedExecutionException 如果没有补救方法, 抛出该异常
     */
    void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19




二、线程池 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;
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94

文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。

原文链接:hanshuliang.blog.csdn.net/article/details/109445676

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。