ThreadPoolExecutor理解
ThreadPoolExecutor组成
ThreadPoolExecutor的核心构造函数:
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.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
根据构造方法可以看才ThreadPoolExecutor主要分为以下几个部分:
- corePoolSize:核心线程池能容纳的线程数
- maximumPoolSize:线程池最大能容纳的线程数(实际是当核心线程池满了之后会进行扩容
maxSize - coreSize
) - keepAliveTime: 当线程执行完毕之后等待被销毁的时间
- workQueue:存放等待执行的任务,是一个BlockingQueue。
- ThreadFactory: 线程的构造方法
- RejectedExecutionHandler: 线程被拒绝加入线程池时执行的策略
等待队列 BlockingQueue
- ArrayBlockingQueue : 基于数组的先进先出队列,构造时必须指明大小;
- LinkedBlockingDeque : 基于链表的队列,如果构造时没有指明大小,则默认为
Integer.MAX_VALUE
; - SynchronousQueue : 一次只会执行一个Thread的队列。
线程池新入线程
线程池的策略,当来新线程时:
- 如果线程池中有空闲线程,就复用空闲线程。
- 如果没有空闲线程,就将新线程加入等待队列。
- 如果来的线程太多,等待队列也满了,就临时扩容到
maxPoolSize
,相当于使用了一个临时线程池来使用。 - 如果扩容还是无法满足,就执行拒绝策略。具体的拒绝策略根据创建时的handler决定。
- 线程池通过使用一个
Woker
负责循环从等待队列中获取线程执行。
ThreadPoolExecutor用法
1. 直接实例化一个
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
2. 使用Executors
的new****Pool()
方法创建ExecutorService:
每一个new****Pool方法实质也是调用ThreadPoolExecutor的构造方法,只是传入的参数是设定好的。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
- FixedThreadPool : 核心线程池大小和最大线程池一样,缓存队列为LinkedBlokingQueue,超出线程池满了之后进入的线程都会被加入等待队列。
- ScheduledThreadPool : 核心线程池大小用户决定,最大线程池大小为
Integer.MAX_VALUE
。等待队列为:DelayedWorkQueue
。 - SingleThreadExecutor : 核心线程池为0,意味着新的线程马上就会被创建。
ThreadPoolExecutor和ExecutorService的区别
首先Executor
和ExecutorService
都是接口,ThreadPoolExecutor
是类。
通过Executors.new****Pool
创建线程池返回的都是ExecutorService
的实例,相当于是调用的ThreadPoolExecutor
的构造方法,返回的是它的父类AbstracExecutorService
的实例。AbstracExecutorService
又是实现了ExecutorService
接口的抽象类。