ThreadPoolExecutor 线程池详解
一. ThreadPoolExecutor 的介绍
ThreadPoolExecutor 的核心会用到实现了 AQS 中的独占式同步队列的 Worker,Worker 主要用于新建线程以及对线程状态的管理,其中 ThreadPoolExecutor 还会维护一个核心线程数,如果添加的线程数超过了核心线程数,则会将线程加入到 BlockingQueue 类型的等待队列中。
二. ThreadPoolExecutor 的使用
1. 创建线程池
ThreadPoolExecutor 的构造函数会有许多参数,每一个参数都需要大概的了解。
- corePoolSize:核心线程数,只要提交任务就会新建一个线程,不管是否有空闲的线程存在都会新 建,直到执行任务的线程数到达核心线程数才不会再创建。使用
prestartAllCoreThreads()
方法会预先提前创建并启动线程。 - maximumPoolSize:最大线程数,最大线程数等于核心线程数加上队列中的线程数。如果使用了无界队列,此项会无效。
- keepAliveTime:队列中闲置线程的最大等待时间。
- unit:等待时间的时间单位。
- workQueue(BlockingQueue 类型):同步队列的类型,有多种队列可以选择。
- threadFactory(ThreadFactory类型):用于创建线程的线程工厂,ThreadFactory 接口包含了一个
newThread()
方法,自定义实现此方法用来创建线程。 - handler(RejectedExecutionHandler 类型):饱和策略,在队列已满的情况下,用来处理新任务的策略。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
workQueue 等待队列
等待队列有四种类型可以选择。
- ArrayBlockingQueue:基于数组的 FIFO (先进先出) 类型的有界队列
- LinkedBlockingQueue:基于链表的 FIFO (先进先出) 类型的阻塞队列,构造函数中可以选择队列的大小,但是在 Executors 中使用的是无界队列。
- SynchronousQueue:一个不储存元素的阻塞队列,后一个线程的插入操作必须等待前一个线程调用移除操作。
- PriorityBlockingQueue:具有优先级的无界阻塞队列。
handler 饱和策略
饱和策略,在队列已满的情况下,用来处理新任务的策略。
- AbortPolicy:默认策略,直接抛出异常。
- CallerRunsPolicy:直接执行调用者的任务。
- DiscardPolicy:不处理
- DiscardOldestPolicy:去除队列中最近的一个任务,并执行当前任务。
2. 向线程池提交任务
向线程池提交任务分为两种,execute()
和 submit()
。execute()
没有返回值,submit()
会返回一个 Future<?>
类型的对象,通过 Future<?>
的 get()
可以获取任务的返回值。
- execute()
executor.execute(() -> {
// 运行程序
});
- submit()
Future<?> future = executor