ThreadPoolExecutor构造函数的几个关键参数的含义
/**
* Creates a new {@code ThreadPoolExecutor} with the given initial
* parameters.
*
* @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 threadFactory the factory to use when the executor
* creates a new thread
* @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 threadFactory} or {@code handler} is null
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler){
}
corePoolSize
- corePoolSize代表的是核心线程数,当一开始线程池中的任务数量N小于核心线程数的时候,线程池会不断新建线程来处理用户提交进来的任务即使有线程空闲。corePoolSize表示线程池通常情况下会保留的线程数量,当任务数量超过核心线程数量的时候,线程池就要用到参数workQueue了。
workQueue
- 当用户提交的任务数量变多了,这时候线程池中的线程的数量已经达到了核心线程数,那么只能将提交过来的任务暂时存储在workQueue中,当线程处理完当前的任务后就会来workQueue中获取任务,如果队列中没有任务,那么当前线程就会阻塞在队列上,等待新任务的到来。
- 其中工作队列可简单分为两种:
- 无界队列
- 如果传入的是无界队列,那么意味着用户可以源源不断的提交任务到线程池,而不需要担心线程池拒收,例如LinkedBlockingQueue.
- 有界队列
- 如果传入的是有界队列,例如ArrayBlockingQueue,那就需要考虑队列存满了的话,就会创建额外的普通线程来干活了,这就需要用到参数maximumPoolSize.
- 无界队列
maximumPoolSize
- 此时的话核心线程都在干活,而且工作队列也存满了任务。如果还是有新任务提交进来,那么线程池就会再创建一些新的线程来执行任务,当然这些线程的数量也不能太多,毕竟资源有限,maximumPoolSize就是要来限制这些线程的数量上限的。如果此时普通线程数量的数量也达到了了上限,那么此时再来新任务的话就可能会被拒绝了,那么接下来就会用到RejectedExecutionHandler这个参数了。
RejectedExecutionHandler
-
线程池提供了4种拒绝策略
- AbortPolicy
- AbortPolicy策略会抛出一个RejectedExecutionException异常给用户,告诉它任务被拒绝了。
- DiscardPolicy
- DiscardPolicy策略当任务来临时候不会给用户任何反馈,悄无声息拒绝任务。
- DicardOldestPolicy
- DicardOldestPolicy策略比较霸道,它会直接将最早存储在工作队列的任务丢弃掉,然后再试图执行当前提交进来的任务。
- CallerRunsPolicy
- CallerRunsPolicy策略,虽然线程池中的线程工人不帮忙处理任务了,但是他会占用用户线程去处理当前任务,这也就意味着用户线程要处理完当前任务才可以做其他事情。
- AbortPolicy
-
threadFactory
- 名如其意,线程工厂,主要用来创建线程的,例如我们想让线程池中的线程做一些定制化的工作就可以自己来定义线程工厂。
Executors中几个常用的静态方法。
- 综上看,我们发现创建一个线程池还是挺多参数的,还是有点麻烦,贴心的SDK帮我们都考虑到了,Executors内部的话提供了几个静态工厂方法。
- newFixedThreadPool(int nThreads) 可以创建一个固定线程数量的线程池,同时它的工作队列是一个无界队列。
- newSingleThreadExxcutor()可以创建只有一个线程工作的线程池,同时它的工作队列也是无界队列。
- newCacheThreadPool()可以创建一个没有上限工作现场的线程池,它使用了SynchronousQueue只要有任务过来,如果有空闲线程优先让空闲线程执行任务,没有空闲线程就会创建线程。
- newSingleThreadScheduledExecutor()创建的是一个具有延迟和循环执行任务线程池,同时它内部也只有一个线程,它的工作队列是一个具有延迟功能的队列DelayedWorkQueue.