首先备上核心源码:
/**
* Creates a new {@code ThreadPoolExecutor} with the given initial
* parameters and default thread factory.
*
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param maximumPoolSize the maximum number of threads to allow in the
* pool
* @param keepAliveTime when the number of threads is greater than
* the core, this is the maximum time that excess idle threads
* will wait for new tasks before terminating.
* @param unit the time unit for the {@code keepAliveTime} argument
* @param workQueue the queue to use for holding tasks before they are
* executed. This queue will hold only the {@code Runnable}
* tasks submitted by the {@code execute} method.
* @param handler the handler to use when execution is blocked
* because the thread bounds and queue capacities are reached
* @throws IllegalArgumentException if one of the following holds:<br>
* {@code corePoolSize < 0}<br>
* {@code keepAliveTime < 0}<br>
* {@code maximumPoolSize <= 0}<br>
* {@code maximumPoolSize < corePoolSize}
* @throws NullPointerException if {@code workQueue}
* or {@code handler} is null
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
一、参数详解
(1)corePoolSize 核心线程数
核心线程数量是线程池维护的一个可设置的定值,当任务提交到线程池,线程数小于核心线程数时便会直接创建线程执行,并且不会销毁(除非设置了allowCoreThreadTimeOut),直到达到核心线程数。
(2)maximumPoolSize 最大线程数
一个任务提交到线程池,首先会查找有没有空闲并存活的线程,有便将任务提交给线程执行,若没有便会缓存到工作队列,若工作队列也满了,则会创建新线程执行任务,这时候会有一个线程数的上限,这个上限便是最大线程数(maximumPoolSize)。
(3)keepAliveTime 空闲线程存活时间
一个线程如果处于空闲状态,并且当前线程数量大于核心线程数(corePoolSize),则在指定时间后,该空闲线程就会被销毁,这个时间时由keepAliveTime设定。
(4)unit 空闲线程存活时间单位
keepAliveTime的计量单位
(5)workQueue 工作队列
新任务被提交后,会先进入到此工作队列中,任务调度时再从队列中取出任务。
1)ArrayBlockingQueue
基于数组的有界阻塞队列,按FIFO排序。
2)LinkedBlockingQuene
基于链表的无界阻塞队列(其实最大容量为Interger.MAX),按照FIFO排序。
3)SynchronousQuene
一个不缓存任务的阻塞队列,生产者放入一个任务必须等到消费者取出这个任务。
4)PriorityBlockingQueue
具有优先级的无界阻塞队列,优先级通过参数Comparator实现。
(6)threadFactory 线程工厂
创建一个新线程时使用的工厂,可以用来设定线程名、是否为daemon线程等等
(7)handler 拒绝策略
当工作队列中的任务已满并且线程池中的线程数量也达到最大,这时如果有新任务提交进来,拒绝策略就是解决这个问题的,jdk中提供了4中拒绝策略:
1)CallerRunsPolicy
在调用者线程中直接执行被拒绝任务的run方法,除非线程池已经shutdown,则直接抛弃任务。
2)AbortPolicy
直接丢弃任务,并抛出RejectedExecutionException异常。
3)DiscardPolicy
直接丢弃任务,什么都不做。
4)DiscardOldestPolicy
抛弃最早进入队列的那个任务,然后尝试把这次拒绝的任务放入队列。
二、流程详解
上面有关线程池的七个参数与线程池的执行流程息息相关。
线程池的执行流程:
(1)当任务提交到线程池时,假如当前线程数小于核心线程数,直接创建线程执行,并且不会销毁,直到达到核心线程数。
(2)当核心线程都在执行还有任务提交时,任务放在阻塞队列中。
(3)阻塞队列也满了以后,继续创建线程执行任务,直到达到最大线程数。
(4)最大线程也满了以后,执行对应的拒绝策略。
(5)当线程空闲下来以后,线程在达到线程空闲等待时间后销毁,直至数量降低至核心线程数。
三、线程池中的相关类库分析
1.线程池相关UML简要类图关系
2.Executor和ExecutorService的区别
ExecutorService 接口继承了 Executor 接口,是 Executor 的子接口
Executor | ExecutorService |
Executor 是 Java 线程池的核心接口,用来并发执行提交的任务 | ExecutorService 是 Executor 接口的扩展,提供了异步执行和关闭线程池的方法 |
提供execute()方法用来提交任务 | 提供submit()方法用来提交任务 |
execute()方法无返回值 | submit()方法返回Future对象,可用来获取任务执行结果 |
Executor 接口定义了 execute()方法用来接收一个Runnable接口的对象 | ExecutorService 接口中的 submit()方法可以接受Runnable和Callable接口的对象 |
不能取消任务 | 可以通过Future.cancel()取消pending中的任务 |
没有提供和关闭线程池有关的方法 | 提供了关闭线程池的方法shutdown() |
3.Executors和ThreadPoolExecutor区别
Executors类和ThreadPoolExecutor都是util.concurrent并发包下面的类, Executos下面的newFixedThreadPool、newScheduledThreadPool、newSingleThreadExecutor、newCachedThreadPool底线的实现都是用的ThreadPoolExecutor实现的,所以ThreadPoolExecutor更加灵活。
//newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
//newFixedThreadPool
public newFixedThreadPool(int corePoolSize,//核心线程数
int maximumPoolSize,//最大线程数
long keepAliveTime,//空闲存活时间
TimeUnit unit,//单位
BlockingQueue<Runnable> workQueue,//队列
RejectedExecutionHandler handler) {//拒绝策略
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}