首页 > 其他分享 >线程池addWorker执行流程(添加工作线程)

线程池addWorker执行流程(添加工作线程)

时间:2023-07-10 10:11:10浏览次数:38  
标签:状态 rs 工作 添加 线程 SHUTDOWN ctl addWorker

  1 //添加工作线程
  2 private boolean addWorker(Runnable firstTask, boolean core) {
  3 //    对线程池状态的判断以及对工作线程数量的判断
  4 //    外层for循环的标识
  5         retry:
  6         for (;;) {
  7 //            获取ctl值
  8             int c = ctl.get();
  9 //            拿到线程池的状态
 10             int rs = runStateOf(c);
 11 
 12             // 如果当前线程状态不是RUNNING,再次做后续判断,查看当前任务是否可以不处理
 13             if (rs >= SHUTDOWN &&
 14 //                    线程池状态为SHUTDOWN,并且任务为空,并且工作队列不为空
 15 //                    如果同时满足了这三个要求,那就是要处理工作队列当前中的任务
 16                     ! (rs == SHUTDOWN &&
 17                             firstTask == null &&
 18                             ! workQueue.isEmpty()))
 19 //                只要不是RUNNING状态,不处理新任务
 20 //                如果是SHUTDOWN状态,并且满足了之前addWorker(null,false),并且工作队列有任务时,需要创建线程
 21                 return false;
 22 
 23             for (;;) {
 24 //                获取当前工作线程数
 25                 int wc = workerCountOf(c);
 26 //                判断工作线程是否大于最大值
 27                 if (wc >= CAPACITY ||
 28 //                        如果是核心线程,是否大于设置的corePoolSize
 29 //                        如果是非核心线程,是否大于maximumPoolSize
 30                         wc >= (core ? corePoolSize : maximumPoolSize))
 31 //                    当前工作线程已经达到最大值
 32                     return false;
 33 //                以CAS对工作线程数+1,如果成功,直接跳出外层for循环
 34                 if (compareAndIncrementWorkerCount(c))
 35 //                    跳出外层for循环
 36                     break retry;
 37 //                重新获取ctl
 38                 c = ctl.get();  // Re-read ctl
 39 //                基于新获取的ctl拿到线程池状态,判断和之前的rs状态是否一致
 40                 if (runStateOf(c) != rs)
 41 //                    说明并发操作导致线程池状态变化,需要重新判断状态
 42                     continue retry;
 43                 // else CAS failed due to workerCount change; retry inner loop
 44             }
 45         }
 46 
 47 //        添加工作线程并启动工作线程
 48 //    工作线程是否启动
 49         boolean workerStarted = false;
 50 //        工作线程是否添加
 51         boolean workerAdded = false;
 52 //        Worker就是工作线程
 53         ThreadPoolExecutor.Worker w = null;
 54         try {
 55 //            new Worker构建工作线程,将任务扔到了Worker中
 56             w = new ThreadPoolExecutor.Worker(firstTask);
 57 //            拿到了Worker中绑定的Thread线程
 58             final Thread t = w.thread;
 59             if (t != null) {
 60 //                加锁
 61                 final ReentrantLock mainLock = this.mainLock;
 62                 mainLock.lock();
 63                 try {
 64 //                   重新获取ctl,拿到线程池的状态
 65                     int rs = runStateOf(ctl.get());
 66 //                   如果满足线程池状态为RUNNING,就添加工作线程
 67                     if (rs < SHUTDOWN ||
 68 //                            如果线程池状态为SHUTDOWN并且传入的任务为null
 69                             (rs == SHUTDOWN && firstTask == null)) {
 70 //                        开始添加工作线程
 71 //                        判断当前线程是否 处于run状态(健壮性判断)
 72                         if (t.isAlive()) // precheck that t is startable
 73                             throw new IllegalThreadStateException();
 74 //                        将构建好的worker对象添加到worklers
 75                         workers.add(w);
 76 //                        获取工作线程个数
 77                         int s = workers.size();
 78 //                        记录工作线程最大值,如果现在的工作线程数大于历史最大值
 79                         if (s > largestPoolSize)
 80                             largestPoolSize = s;
 81 //                        将工作线程添加的标识设置为true
 82                         workerAdded = true;
 83                     }
 84                 } finally {
 85 //                    释放锁
 86                     mainLock.unlock();
 87                 }
 88 //              只要添加工作线程成功,启动线程
 89                 if (workerAdded) {
 90                     t.start();
 91 //                    将工作线程启动的标识设置为true
 92                     workerStarted = true;
 93                 }
 94             }
 95         } finally {
 96             if (! workerStarted)
 97 //                如果启动工作线程失败,做的补救操作
 98 //                判断之前创建工作线程是否成功,如果成功,将workers中当前工作线程移除
 99 //                将工作线程数减一
100 //                尝试将线程池状态变为TIDYING
101                 addWorkerFailed(w);
102         }
103         return workerStarted;
104     }

 

标签:状态,rs,工作,添加,线程,SHUTDOWN,ctl,addWorker
From: https://www.cnblogs.com/zhang12345/p/17540119.html

相关文章

  • 添加虚拟原点降低建图复杂度
    ##需求存在一个大小为$n$的点集$V_1$和大小为$m$的点集$V_2$,$V_1$中的每个点都需要向$V_2$中的每个点连一条边##$n*m$条边![](https://cdn.jsdelivr.net/gh/G-ghy/cloudImages@master/20211007155650.png)当$n$和$m$数值较大或者需要建图多次时,一定概率会超内存或者遍历时超......
  • java 线程等待和唤醒方法
    java线程状态变迁图从图中可以看出Java线程等待方法是将线程从Runnable状态转换为Waiting状态,Java线程的唤醒方法是将线程从Waiting状态唤醒进入Runnable状态在Java中线程的等待和唤醒主要是分为3组:Object.wait()和Object.notify()LockSupport.park()和LockSupport.unp......
  • PPT中单个幻灯片添加不同编号
    情景:一个PPT中会有页码,也会有多个其它的编号,对于页码,好办,可以自动生成,但对于其他自定义的、只想在部分页面添加的编号,则需要写VBA脚本进行处理,使页码和自定义编号共存并真正实现编号在各个幻灯片中的自定义特征。采用如下VBA脚本实现自定义编号:SubAddCustomPageNumber()......
  • 03线程安全
    线程安全发生的终极原因是:内存,寄存器存在时间差。今天突然想到一个很好的例子 解释这个问题:一堂随堂测试,你正在答一道题,老师巡考看到你的答案是正确的,其他同学全部是错误的。晚上老师说道这次考试这道题只有一个同学做对了。但是老师不知道你在他走后,修改了答案。最终考试试卷......
  • 线程池excute方法执行流程
    1//线程池execute方法执行流程2publicvoidexecute(Runnablecommand){3//非空判断,判断提交的任务是否为空4if(command==null)5thrownewNullPointerException();6//获取ctl属性7intc=ctl.get......
  • 线程创建
    三种创建方式Threadclass继承Thread类Runnable接口实现Runnable接口Callable接口实现Callable接口Thread自定义线程类继承Thread类重写run()方法,编写线程执行体创建线程对象,调用start()方法启动线程//创建线程方式一:继承Thread类,重写run()......
  • 将子系统的Ubuntu on Windows添加到鼠标右键启动
    文章转载自博客园helios0210的文章,请转到原文链接:为WSL添加右键启动-helios0210-博客园(cnblogs.com)1,找到WSL的安装路径(可以通过Everything直接搜索ubuntu.exe找到)WSL是在MicrosoftStore上安装的,所以我们去C:\Windows\SystemApps,这个文件夹有权限我们想办法打开然后在.......
  • 动态库单独添加Address Sanitizer
    原文地址:https://www.cnblogs.com/liqinglucky/p/address-sanitizer-in-library.htmlAddressSanitizer集成的原理是在汇编过程中(参考:程序编译过程与运行时内存-liqinglucky-博客园(cnblogs.com))编译出.o文件时就将AddressSanitizer的运行时库替换malloc()/free()实现内存......
  • 给input文本框添加灰色提示文字
    灰色提示功能大家都见到很多网站的文本框都有灰色提文字,一点即消失,鼠标一开又出现(没填写状态下)用下面这段短短的代码就可以实现啦!将这段代码加载input中!value="你的提示文字"onFocus="if(value==defaultValue){value='';this.style.color='#000'}"onBlur="if(!value){value=de......
  • SpringBoot 集成异步线程调用
    步骤:1、在自动审核的方法上加上@Async注解(标明要异步调用)2、在文章发布成功后调用审核的方法3、在自媒体引导类中使用@EnableAsync注解开启异步调用 ......