ThreadPoolExecutor 是JAVA中用来生成可配置线程池的一个类。我们平时使用的newCachedThreadPool 、newFixedThreadPool、 newSingleThreadExecutor 都是通过调用ThreadPoolExector来生成的。
ThreadPoolExecutor构造函数
ThreadPoolExecutor 的基础构造器含有七个参数:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory, RejectedExecutionHandler handler){
//...
}
- corePoolSize:核心池中线程的数量。
- maximumPoolSize:线程池最大拥有线程数量。
- keepAliveTime: 线程空闲后可以存活的时间。
- unit:keepAliveTime 的单位。
- workQueue: 当线程池中线程数量达到corePoolSize后,用来缓存新提交(通过execute()方法)的任务的队列。
- threadFactory: 线程池中用来新生成线程的工厂方法。可以设置新生成thread的属性。
- RejectedExecutionHandler: 线程池在异常情况下的拒绝策略。
ThreadPoolExecutor 的基本工作流程
当有新任务通过ThreadPoolExecutor的execute()方法提交后
- 如果线程池中线程的数量少于corePoolSize,则会直接生成新的线程来执行任务。
- 如果线程池中的线程数量等于或大于corePoolSize,则线程池会首先尝试将任务加入workQueue中,如果不能加入队列,线程池会创建新的线程。如果此时线程池中线程数量已经达到了maximumPoolSize,线程池会根据rejectedExecutionHandler设置的策略来处理。
补充
- 不在核心池中的线程空闲一段时间后(keepAliveTime)会被杀掉。核心池中的线程空闲后不会被杀掉,但是可以通过设值allowCoreThreadTimeout(true)来改变这种情况。
- 一般情况下,在线程池中的数量未达到corePoolSize时,每次线程池新接到任务时会创建一个线程。可以通过设值ensurePrestartCoreThread() 或preStartCoreThread()来提前启动一个空闲线程。
BlockQueue的三种类型
- SynchronusQueue
充当了一个传递员的角色。当试图将任务添加在SynchronusQueue中时,会不成功,因此线程池会启动新的线程去执行任务。 - LinkedBlockingQueue
可以接收任意多的任务入队等待。 - ArrayBlockingQueue
有界的阻塞队列。
拒绝接收任务的策略
当workQueue不能缓存任务,线程池也不能创建新的线程时,线程池会出错,此时根据设值的RejectedExecutionHandler,会有不同的行为。
内置的的Hander有AbortPolicy(直接抛出rejectException),CallerRunsPolicy(使用调用者的线程执行), DiscardPolicy(直接丢弃任务),DiscardOldestPolicy(丢弃等待队列对头任务)。
Executor工厂方法中通过配置ThreadPoolExecutor构造函数实现的几种线程池
- newCacheThreadPool
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS,new SynchronusQueue<Runable>());
}
- newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads,nThreads,0L,TimeUnit.MiLLiSECONDS,new LinkedBlockingQueue<Runable>());
}
线程池中至多有n个线程。
- newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runable>()));
}
同一时刻只有一个线程在执行,相当于任务会依次顺序的执行。如果这个线程挂掉的话,线程池会重新启动一个新的线程。