线程池用起来比较简单,但其内部就像一台仪器,需要各个部分相互协作来完成相应的功能。设计模式就用了工厂模式、策略模式、代理模式以及模板模式。ThreadPoolExecutor类图如下:
DefaultThreadFactory是线程工厂,实现了ThreadFactory,其中newThread()方法是创建线程的方法,这里使用了工厂模式,封装了线程的创建过程。
poolNumber用来统计线程工厂的个数,同时也是线程池名称的一部分;
threadNumber用来记录每个线程工厂创建了多少个线程,是线程名称的一部分。
Worker继承了AQS,实现了Runnable接口,这里使用了代理模式,对任务线程的run()方法进行了加强。WorKer继承了AQS,自己实现了简单的不可重入锁,其中state=0表示锁未被获取状态,state=1表示锁已经被获取的状态,state=-1是创建Worker时默认的状态,创建时设置为-1是为了避免该线程在运行runWorker()方法前被中断。
firstTast:记录了该工作线程执行的第一个任务
thread:是需要执行的任务线程
RejectedExecutionHandler:饱和策略,当队列满并且线程个数达到maximumPoolSize后采取的策略,这里使用了策略模式。
AbortPolicy:抛出异常(默认情况下使用该策略)
CallerRunsPolicy:使用调用者所在线程运行任务
DiscardOldestPolicy:调用poll弹出BlockingQueue的队头元素,执行当前任务
DiscardPolicy:默默丢弃,抛出异常
ThreadPoolExecutor继承了AbstractExecutorService,AbstractExecutorService中的submit()方法使用了模板模式。重要属性其含义如下。
corePoolSize:线程池核心线程数
maximumPoolSize:线程池的最大线程数
workQueue:阻塞队列,用来存放任务线程
threadFactory:线程工厂,用来创建线程
handler:饱和策略,默认情况下使用AbortPolicy
keepAliveTime:存活时间。如果线程池中的线程数量比核心线程数量多,并且是闲置状态,这些线程的最大存活时间
TimeUnit:存活时间的单位
clt:用来记录线程池中线程的个数和线程池的状态。线程池通过线程池的状态来控制任务的执行。
线程池的状态如下:
RUNNING:接受新任务并处理阻塞队列中的任务线程
SHUTDOWN:拒绝新任务但是处理阻塞队列中的任务
STOP:拒绝新任务并抛弃阻塞队列中的任务,同时中断正在处理的任务
TIDYING:所有任务执行完(包含阻塞队列里的任务)后,当前线程池活动线程数为0,将调用terminated()方法
TERMINATED:终止状态,调用terminated方法执行完后的状态。
线程池状态的转换
RUNNING -->SHUTDOWN:显示调用shutdown()方法,获取隐式调用finalize()方法里面的shutdown()方法
RUNNING或SHUTDOWN)-->STOP:显示调用shutdownNow()方法
SHUTDOWN --> TIDYING :当线程池和任务队列都为空时
STOP-->TIDYING:当线程池为空时
TIDYING -->TERMINATED:当terminated()方法执行后
参考:《java并发编程之美》