ctl属性:其前三位是运行状态位,后29位是线程个数
注:增加work时有重入锁
主要步骤
获取当前线程池的状态,如果是STOP,TIDYING,TERMINATED状态的话,则会返回false,如果现在状态是SHUTDOWN,只有在要运行的任务为空且还有还有工作任务时才可以添加线程,其他shutdown时不允许创建线程(线程池的状态不符合直接返回)
通过自旋的方式,判断要添加的Worker是否是corePool,如果是的话,那么则判断当前的workerCount是否大于corePoolsize,否则则判断是否大于maximumPoolSize,如果满足的话,说明workerCount超出了线程池大小,直接返回false。如果小于的话,那么判断是否成功将WorkerCount通过CAS操作增加1,如果增加成功的话。则进行到第3步,否则则判断当前线程池的状态,如果现在获取到的状态与进入自旋的状态不一致的话,那么则通过continue retry重新进行状态的判断。(判断是线程个数不大于最大值,不大于最大线程数的话自旋通过cas增加线程数,cas成功进入3步,cas失败的话判断线程池状态发生改变1开始重新判断线程池状态,只是线程数发生变化的话内部循环自旋即可)
如果满足了的话,那么则创建一个新的Worker对象,然后获取线程池的重入锁后,判断当前线程池的状态,如果当前线程池状态为STOP,TIDYING,TERMINATED的话,那么调用decrementWorkerCount将workerCount减一,然后调用tryTerminate停止线程池,并且返回false。(获取锁判断线程池的状态是运行中或者finlize中,是的话添加。添加成功后启动,失败后处理下失败)
注:ctl打包了运行状态runState和已被允许启动但不允许停止的工人数workerCount,高三位表示运行状态。双层for循环是因为最内层是需要cas,内层在cas失败,但是线程的运行状态没有改变只是work数量改变时继续cas即可,即最内层的循环。如果线程池的运行状态改变了,则需要重新读取线程池的运行状态。而外层是需要重新读取运行状态的。