线程池源码解析_one:Executors.newFixedThreadPool(nthreads):
1、构造函数
传入参数:核心线程工作者数量
关键类:ThreadPoolExecutor
传参:corePoolSize:核心工作者数量、maximumPoolSize:最大工作者数量、keepAliveTime:(在fixedThreadPool中无用)、unit:(在fixedThreadPool中无用)、workQueue:队列(当工作者数量超过预定的核心工作者数量时将新增的任务放入队列)
注:
a、工作者(Worker):新增的任务线程会放进此Worker类中,该Worker 也是一个Runnable线程,该Worker内部也会维护一个Thread实例, 调用thread实例的start方法,即执行该Worker线程,同时在Worker 的run方法中调用新增的任务的run方法
b、Worker存放在HashSet中
2、submit提交任务:
ThreadPoolExecutor-继承->AbstractExecutorService-实现->ExecutorService(接口)-继承->Executor(接口)
最终执行的是ThreadPoolExecutor中的execute()方法
查看该方法前需要了解表示线程的状态以及工作者数量的方式:
Ctl:该数值包含了线程池的状态(高三位表示)和工作者的数量(低29位表示),该类是院子操作,底层是Unsafe类cas操作
CtlOf():rs表示状态(RUNNING,SHUTDOWN,STOP,TIDYING,TERMINATED), wc表示工作者数量,通过|操作得到既包含状态又包含数量的数值
RunStateOf():将ctl值传入得到高三位数值,即可获知当前状态
WorkerCountOf():将ctl值传入得到低29位,即可获取当前工作者数量
Execute方法过程:
(1)、首先得到ctl数值,判断当前的工作者数量是否小于预定的核心工作者数量,如果小于则调用addWorker()方法,如果不满足看(3)
(2)、addWorker()方法:
首先会根据当前状态判断是否能够添加新任务:
a、如果当前状态大于shutdown,不能添加新任务
b、如果当前状态等于shutdown,且firstTask不等于null,不能添加新任务
c、如果当前状态等于shutdown,且firstTask等于null,且队列为空,不能添加新任务
然后进入第二层无限for循环,在此判断当前工作真数量是否大于核心工作真数量,如果大于则不能添加新任务,如果满足则需要将当前工作者数量增加1,调用的是compareAndIncrementWorkerCount,如果增加1成功则返回true,如果不成功则说明这期间有其他的线程已经修改原来的数值,则进而判断状态是否已经改变,如果已经改变则继续最开始循;如果未改变则进入内层无限for循环,重新获取最新值,再次重复判断,最终要么成功增加1,要么当前工作者数量大于核心工作者数量,不能添加新任务而退出
compareAndIncrementWorkerCount增加1成功,则往下执行:将新增的任务包装成Worker类,然后加锁(加锁的原因则是因为需要将worker添加到成员变量workers中),再次判断状态(小于shutdown或者等于shutdown但是任务为null),满足条件将worker添加到workers中,解锁,若添加成功则启动worker(详解看(4)),若启动不成功,则需要将worker从workers中移除,并且将ctl值减一
(3)、如果当前状态是running,且将任务添加到队列成功(此队列为LinkedBlockingQuene,双向链表),则再次检测状态,如果已经改变了状态且将任务成功从队列中remove,则调用拒绝策略(此处为AbsortPolicy,实际上是抛出异常),如果还在running状态,但是当前工作者数量已经为0,则添加一个空的工作者;如果当前状态不是running,则尝试去执行任务即调用addWork(),如果不成功则调用拒绝策略
(4)、执行任务过程:
任务启动调用的是Worker类中的thread的start方法,实际上构造Thread类的时候传入的就是Worker实例本身,所以start实际执行的就是Worker的run方法,run方法中调用了runWorker方法,runWorker方法中调用了任务的run方法
RunWorker()方法:
首先取出Worker的firstTask赋值给task,然后将firstTask置为空,则判断task是否null,不为null则先获取锁,然后执行firstTask的run方法(即我们自定义的runnable),执行完以后则从队列中取任务,此时调用的是getTask()方法
GetTask()方法:
循环从队列中取任务,返回null的条件:
a、如果状态时shutdown且队列为null,则返回null
b、如果状态大于shutdown则返回null
c、如果工作者数量大于所允许的最大工作者数量,且能够将ctl值减一,则返回null
(还有一些条件存在疑问,待研读)
fixedThreadPool使用take()获取队列中的任务(poll()方法有待研读)