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

举报
韩曙亮 发表于 2022/01/10 23:38:16 2022/01/10
【摘要】 文章目录 一、线程池 execute 方法源码解析二、线程池 execute 方法完整源码及注释 一、线程池 execute 方法源码解析 进入 ThreadPoo...





一、线程池 execute 方法源码解析



进入 ThreadPoolExecutor 中 , 查看线程池任务执行方法 public void execute(Runnable command) 的源码 ;

用户向线程池中提交任务时 , 主要执行了三个步骤 ,



第一步 : 核心线程数不足的情况

如果当前运行的线程 , 小于核心线程数 , 那么 创建一个新的核心线程 ,

将 传入的任务 作为该线程的 第一个任务 .

调用 addWorker 方法 , 会原子性 检查运行状态和任务数量 ;

如果在 不应该添加线程的情况下 执行添加线程操作 , 就会发出错误警报 ;

如果该方法返回 false , 说明 当前不能添加线程 , 此时就不要执行添加线程的操作了 ;


源码解析 : 如果当前的线程数小于核心线程数 , 则调用 addWorker(command, true) , 添加核心线程 , 第二个参数 true 表示该添加的线程是核心线程 ;

        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5


第二步 : 任务放入 线程池任务队列 成功情况


如果任务被成功放入 线程池任务 队列 , 不管我们此时是否应该添加线程 , 都需要进行 双重验证 ;

双重验证 : 添加到任务队列 时验证一次 , 添加到线程执行 时验证一次 ;

可能存在这种情况 , 在上次验证线程运行状态之后 , 有可能 该线程就立刻被销毁了 ;

也可能存在进入该方法后 , 线程池被销毁的情况 ;

因此我们 反复验证线程状态 , 如果需要在线程停止时回滚队列 , 如果没有线程就创建新线程 ;


先调用 isRunning( c ) 判断线程是否在运行中 , 只有运行状态时 , 线程池才能接收任务 ,

将任务添加到队列 中 , 调用 workQueue.offer(command) 方法实现 ,

然后又调用 isRunning(recheck) 判定该线程是否是运行状态 ,

如果不在 , 那么调用 remove(command) 移除该命令 , 然后调用 reject(command) 拒绝执行该命令 ,

        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }

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

两个核心的操作 :

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


第三步 : 任务放入 线程池任务队列 失败情况

如果不能将任务放入队列中 , 尝试创建一个新线程 ;

如果创建线程失败 , 说明当前线程池关闭 , 或者线程池中线程饱和 , 此时 拒绝执行该任务 ;

        else if (!addWorker(command, false))
            reject(command);

  
 
  • 1
  • 2




二、线程池 execute 方法完整源码及注释



public class ThreadPoolExecutor extends AbstractExecutorService {

    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /*
         * 进行以下三个步骤处理:
         *
         * 1. 如果当前运行的线程 , 小于核心线程数 , 那么创建一个新的核心线程 , 
         * 将传入的任务作为该线程的第一个任务 . 
         * 调用 addWorker 方法 , 会原子性检查运行状态和任务数量 ; 
         * 如果在不应该添加线程的情况下执行添加线程操作 , 就会发出错误警报 ; 
         * 如果该方法返回 false , 说明当前不能添加线程 , 此时就不要执行添加线程的操作了 ; 
         *
         * 2. 如果任务被成功放入 线程池任务 队列 , 不管我们此时是否应该添加线程 , 都需要进行双重验证 ;
         * 双重验证 : 添加到任务队列时验证一次 , 添加到线程执行时验证一次 ; 
         * 可能存在这种情况 , 在上次验证线程运行状态之后 , 有可能该线程就立刻被销毁了 ;
         * 也可能存在进入该方法后 , 线程池被销毁的情况 ; 
         * 因此我们反复验证线程状态 , 如果需要在线程停止时回滚队列 , 如果没有线程就创建新线程 ;
         *
         * 3. 如果不能将任务放入队列中 , 尝试创建一个新线程 ; 
         * 如果创建线程失败 , 说明当前线程池关闭 , 或者线程池中线程饱和 , 此时拒绝执行该任务 ; 
         */
        int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        /*
        	先调用 isRunning(c) 判断线程是否在运行中 , 只有运行状态时 , 线程池才能接收任务 , 
        	先将任务添加到队列中 , 调用 workQueue.offer(command) 方法实现 , 
        	然后又调用 isRunning(recheck) 判定该线程是否是运行状态 , 
        	如果不在 , 那么调用 remove(command) 移除该命令 , 然后调用 reject(command) 拒绝执行该命令 , 
         */
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        else if (!addWorker(command, false))
            reject(command);
    }
}

  
 
  • 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

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

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

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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