ThreadPoolExecutor的Worker工作线程主要做了校验线程池状态和工作线程个数。添加工作线程并且启动工作线程。
校验线程池状态和工作线程个数代码展示
-
需要明确两点首先,外层循环校验线程池状态。
-
内层循环校验工作线程个数。
-
retry标记为给外循环起个名字。方便最内层的for循环跳出循环。
-
int c = ctl.get(); 获取ctl
-
int rs = runStateOf©; 拿到ctl高三位的值
-
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false; 这一部分是线程池状态的判断。会进入添加的条件是线程池状态是SHUTDOWN。并且阻塞队列中有任务,而且工作线程个数为0。添加一个工作线程去处理阻塞队列中的任务。
要是上述的理想条件不满足那就false。 -
接下来的是工作线程个数的判断。
-
int wc = workerCountOf©; 获取ctl低29位的值那就是获取工作线程的个数。
-
如果工作线程个数大于最大值那就不添加。返回false。还有一个判断是判断当前线程是核心还是非核心。核心是基于corePoolSize去判断;非核心是基于corePoolSize去判断。
-
compareAndIncrementWorkerCount©。这里采用CAS的方式对ctl进行加1;
-
要是上述的+1失败了。重新获取ctl的值。然后将线程的状态和之前的进行比较。要是有区别说明有变化,跳出一次外层for循环。
添加工作线程并启动工作线程源码分析
- 声明了三个变量。
- 工作线程启动没有。false。没有启动
- 工作线程添加了没有。false。没有添加。
- 工作线程默认为null。
- try内部的方法分析。
- w = new Worker(firstTask)。构建工作线程并且将任务传递进去。
- final Thread t = w.thread;获取上面构建的word的thred对象。
- t != null。对Thred对象进行判断。在new word的时候是通过Thred工厂去构建Thred对象。然后交给worker对象。要是为null则证明线程工厂有问题。
- final ReentrantLock mainLock = this.mainLock;加锁保证使用workers对象以及对largestPoolSize变量相加线程的安全性。
- int rs = runStateOf(ctl.get());再次获取线程池的状态。
- if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null))
小于SHUTDOWN 这个标记说明线程池的状态是RUNNING状态正常。并且firstTask 为null添加非核心工作线程处理阻塞队列中的任务。 - t.isAlive()。这里是校验可以添加工作线程但是不能启动线程。要是启动了那就抛出IllegalThreadStateException异常。
- workers.add(w);这里的workers 是 private final HashSet workers = new HashSet();
- int s = workers.size();拿到线程的线程数。
- if (s > largestPoolSize)。当前线程数大于最大线程数更新最大线程数。
- if (workerAdded) {
t.start();
workerStarted = true;
}
线程添加成功启动工作线程 - if (workerAdded) {
t.start();
workerStarted = true;
}
要是添加工作线程失败处理失败的工作线程。
添加线程失败的操作
- final ReentrantLock mainLock = this.mainLock;涉及到操作works需要加锁。
- tryTerminate();添加线程失败的状态转换操作。。。。。。。。。。。。。