ThreadPoolExecutor,位于 java.util.concurrent; 包中,继承了 AbstractExecutorService 抽象类,间接继承了 ExecutorService 接口。
ThreadPoolExecutor 结构
ThreadPoolExecutor
是一个可被继承 ( extends ) 的线程池实现,包含了用于微调的许多参数和钩子。
ThreadPoolExecutor 中定义了众多的参数和方法,此处仅对其比较重要的参数进行学习。
构造函数
ThreadPoolExecutor 有多个参数不同的构造函数,其中参数最完整的定义如下:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, ThreadPoolExecutor.RejectedExecutionHandler handler) {
this.ctl = new AtomicInteger(ctlOf(-536870912, 0));
this.mainLock = new ReentrantLock();
this.workers = new HashSet();
this.termination = this.mainLock.newCondition();
this.submittedCount = new AtomicInteger(0);
this.lastContextStoppedTime = new AtomicLong(0L);
this.lastTimeThreadKilledItself = new AtomicLong(0L);
this.threadRenewalDelay = 1000L;
if (corePoolSize >= 0 && maximumPoolSize > 0 && maximumPoolSize >= corePoolSize && keepAliveTime >= 0L) {
if (workQueue != null && threadFactory != null && handler != null) {
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
this.prestartAllCoreThreads();
} else {
throw new NullPointerException();
}
} else {
throw new IllegalArgumentException();
}
}
对于线程池初始化的相关参数,可以接释为
- corePoolSize,int,线程池的核心线程数
- maximumPoolSize,int,线程池的最大线程数
- keepAliveTime,long,线程存活时间
- unit,TimeUnit,线程池存活时间的单位
- workQueue,BlockingQueue
,线程池的线程任务队列 - threadFactory,ThreadFactory,线程工厂函数
- 工厂函数可以不指定,默认使用 Executors.defaultThreadFactory() 工厂对象
- handler,ThreadPoolExecutor.RejectedExecutionHandler,线程池队列拒绝策略
- 拒绝策略可以不指定,默认使用 new ThreadPoolExecutor.RejectPolicy() 策略
线程池中线程创建策略
线程工厂函数对象,用于线程池中创建线程对象,如果不指定会使用默认的 Executors.defaultThreadFactory() 工厂对象。
ThreadPoolExecutor 创建的线程池由固定数量的核心线程组成,这些线程在线程池生命周期内始终存在。
如果线程任务数量超过核心线程数,新的任务会被加入到线程队列中,并在核心线程空闲时从队列中读取任务进行执行。
如果任务数量超过核心线程数,且线程队列中也已经加满(有界队列),此时如果最大线程数大于核心线程数,则会增加线程数量来处理新的线程任务,额外增加的非核心线程数会在空闲超过指定时间后被回收。
如果任务数量超过核心线程数,且线程队列中也已经加满(有界队列),并且线程数量已经增加至最大线程数,此时如果有新的线程任务,则会执行线程池的拒绝策略。
线程池线程任务拒绝策略
线程池的线程任务拒绝策略参数 handler ,如果不指定则使用默认的 new ThreadPoolExecutor.RejectPolicy() 策略。
线程池的拒绝策略都定义在 ThreadPoolExecutor 类中,其中的内部接口 ThreadPoolExecutor.RejectedExecutionHandler,有默认的实现策略类五种:
- new ThreadPoolExecutor.RejectPolicy(),直接拒绝新任务的策略
- new ThreadPoolExecutor.DiscardOldestPolicy(),丢弃任务队列中最老的任务的策略
- new ThreadPoolExecutor.DiscardPolicy(),丢弃新任务的策略
- new ThreadPoolExecutor.AbortPolicy(),抛出异常的策略
- new ThreadPoolExecutor.CallerRunsPolicy(),由当前主线程执行新任务的策略
ScheduledThreadPoolExecutor
ScheduledThreadPoolExecutor 也是 java.util.concurrent; 包中的线程池类,且其继承了 ThreadPoolExecutor 类,并实现了 ScheduledExecutorService 接口。
构造函数
ScheduledThreadPoolExecutor 类继承了 ThreadPoolExecutor 类,因此其构造函数基本是在调用父级构造函数,且 ScheduledThreadPoolExecutor 类在初始化时只可以设置核心线程数、工厂对象、以及拒绝策略,代码如下:
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), threadFactory, handler);
}
- ScheduledThreadPoolExecutor 初始化时 corePoolSize 核心线程数是必填的
- 线程池的最大线程数不可修改,使用默认值 Integer.MAX_VALUE
- 线程存活时间不可以修改,使用默认值 0
- 线程池存活时间的单位不可修改,使用默认值 NANOSECONDS
- 线程池的线程任务队列不可修改,使用默认值 new DelayedWorkQueue()
- 工厂函数 threadFactory 和阻塞策略 handler 与 ThreadPoolExecutor 初始化一致,可以指定,不指定则使用父级默认值。
附加功能
ScheduledThreadPoolExecutor 类除了继承 ThreadPoolExecutor 外,还实现了 ScheduledExecutorService 接口,该接口提供了一些功能方法。
- schedule(Callable
callable (Runnable command), long delay, TimeUnit unit) ,方法允许在指定的延迟后执行一次任务
- scheduleAtFixedRate(Runnable command,
long initialDelay, long period, TimeUnit unit), 方法允许在指定的初始延迟后执行任务,然后以一定的周期重复执行,其中 `period` 参数用于指定两个任务的开始时间之间的间隔时间,因此任务执行的频率是固定的。
- scheduleWithFixedDelay(Runnable command,
long initialDelay, long delay, TimeUnit unit), 方法类似于 `scheduleAtFixedRate()` ,它也重复执行给定的任务,但 `delay` 参数用于指定前一个任务的结束和下一个任务的开始之间的间隔时间。也就是指定下一个任务延时多久后才执行。执行频率可能会有所不同,具体取决于执行任何给定任务所需的时间。