线程池的实现原理

runState   线程池的运行状态                        

running:表明线程池在运行当中,可以接受新的任务,也可以处理阻塞队列中的任务。

shutdown:不可以接受新的任务了,但是还可以执行阻塞队列中的任务。

stop:不可接收新任务,不可执行阻塞队列里的任务了,并且尝试终止所有在运行任务。

tidying:所有任务已经终止,执行terminated()

terminated:线程池完全关闭

 

在ThreadPoolExecutor的构造方法中,定义了线程池的核心线程数,最大线程数,过期时间,时间单位,阻塞队列,创建线程的工厂,拒绝策略。下面来看看默认的线程工厂,它到底是如何创建新的线程的。

DefaultThreadFactory实现了ThreadFactory接口,

在DefaultThreadFactory构造方法中确定线程的命名前缀,之后每创建一个线程,poolNumber不变,threadNumber++,并设置线程是否是Deamon线程、线程的优先级等。

 

何时调用newThread()方法呢?Worker是对提交任务的封装,如果调用Worker的构造方法,就会创建一个新的线程中去执行任务。

||左边为真,右边就不再执行了,也就是如果task不为null,就运行firstTask,如果为null,就从阻塞队列获取任务执行。

while (task != null || (task = getTask()) != null)

 

 

 

现在我们来看看线程池的运行原理:当提交任务到线程池中,会调用execute方法

如果当前线程数比核心线程数小,那么就添加一个Worker(也就是创建一个新的线程,去处理这个任务),并直接return。如果已经达到核心线程数,那么新来的任务会插入到阻塞队列中,也就是workQueue.offer(command).如果队列也满了,还有任务到来的话,那么就继续创建新的线程。如果创建新的线程时池子已经达到最大线程数,就采取拒绝策略。

添加Worker的方法:

 

在该方法中会调用new Worker(firstTask)构造函数,创建线程并运行此任务。

 

如何关闭线程池呢?

shutdown()方法会停止接受任务,但是已经提交的任务可以继续执行。该方面将线程池状态改为shutdown,然后中断所有空闲的线程。

在中断所有空闲线程的方法中,有一个tryLock(),如果线程正在执行,是持有锁的,所以tryLock()获取不到,也就不会中断了。

shutdownNow()方法将线程池状态设置成stop,不能再提交任务,已经提交但未执行的任务不能运行,正在运行的任务可继续运行,但会被中断(尝试终止所有在运行任务),返回已经提交但未执行的任务。

这里会中断所有的线程

 

最后都要调用tryTerminate()方法,尝试彻底关闭线程池,会先用CAS将线程池状态改为tidying,最后调用terminated()方法。

 

posted @ 2017-08-17 16:46  bili111  阅读(718)  评论(0编辑  收藏  举报