线程池流程图
execute核心方法
这里不用多说,其实就是线程池的流程图中的所说的,如果小于核心线程数量,创建核心线程,否则往队列仍任务,假设队列也满了,那就创建非核心线程,如果大于了maximumPooSize,也就是说非核心线程也创建不了了,不好意思,那就走reject策略
addWorker
addWorker别看代码比较多,其实核心代码就是通过CAS来增加一个Worker count数,然后跳出循环,创建Worker加锁的方式加入到线程池中workers(HashSet)数据结构中,然后启动Worker
Worker
ThreadPoolExecutor创建了一个Worker并启动了他,我们是不是要看一下Worker是什么玩意?
唉吆喂,Worker竟然继承了AQS并实现了Runnable,加锁的线程,是不是?好吧,那既然是线程了,那看一下他run方法吧:
首先看看一下 task != null || (task = getTask()) != null,这个条件,对于第一次创建核心线程并执行run来说,firstTask是通过 w = new Worker(firstTask)传递过来,给了Worker实例变量了,所以task肯定是不为null的,同意吧?
然后看核心代码task.run,其实就是调用用户自己定义的run方法的逻辑,理解了吧
好了,那比如说我们核心线程的第一个任务运行完了呢?那getTask()就上场了:
其实有三部分核心逻辑 :
关闭线程池
如果已经对线程池进行了shutdown了,那好,等我workerQueue队列任务消费完毕,那我就线程退出
如果已经对线程池进行了stop,我去,好吧,你太暴力了,那就直接退出吧,会在shutdownNow中详细说
非核心线程超时
如果wc > corePoolSize,也就是说有非核心线程,是不是timed为true,然后非核心线程是以workQueue.poll以规定时间来获取任务,此时如果任务是null,没有任务,是不是timedOut=true了,好,然后再循环timed和timedOut都为true了,上述第二个逻辑的if就成立了,那非核心线程的Worker就会退出
阻塞和非阻塞方式获取任务
如果是核心线程,就会阻塞的方式take来拿任务,如果是非核心线程,就会进行poll(time)方式来拿任务
shutdonwNow & shutdown
-
shutdonwNow
advanceRunState(STOP):将线程池的状态改变为STOP,本质上是一个线程标记位的改变
interruptWorkers():对线程池中的所有线程都进行终止(interrupt)操作
这里会对所有的线程都会进行interrupt,那现在就有一个疑问,Worker会在哪里阻塞呢?其实有两处(Worker中):- 对于空闲的线程会在getTask中以take阻塞的方式来拿任务
- 还有就是在task.run中,咱们自己定义业务逻辑如果有可中断的代码,就会被中断
而shutdownNow会对所有的Worker进行interrupt,也可能会对正在运行的任务,如果可以响应中断,就会中断当前正在运行的任务,否则会进行下一次getTask的时候,即运行完当前任务,再下一次获取任务前判断退出Worker线程
- shutdown
interruptIdleWorkers:是interrupt空闲的线程,谁是空闲的线程?怎么来区分,这里AQS就出场了
w.tryLock()是一个很关键的玩意,要知道,如果Worker正在执行任务,正在执行task.run(),这前面肯定是加锁的,所以tryLock是拿不到锁的,所以针对正在运行的Worker线程是不interrupt的
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net