路漫漫其修远兮,吾将上下而求索
线程池的使用
继承Thread类和实现Runnable接口分别提供了单个线程的创建方法,但是线程的创建和销毁是很消耗性能的一种操作,Executor提供了线程池的功能,避免了频繁创建和销毁线程的操作,Executor大体框架如下:
Executor只是一个基础的接口,其下ThreadPoolExecutor提供了不同的构造方法来创建线程池,以及Executoes提供了不同的静态方法来创建线程池
一、ThreadPoolExecutor分析
(一)、主要参数分析
该类中提供了不同参数的构造方法,最多的构造方法包含七个参数,源码中解释如下:
@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
逐一分析:
1、corePoolSiza(int)
**核心线程数量,**即线程池中要保留的线程数,即使没有任务执行。
2、maxnumPoolSize(int)
**最大线程数,**即线程池中允许的线程的最大数量。
3、keepAliveTime(long)
**保持存活时间,**即当线程池中的线程数量大于corePoolSize时,多出的线程的空闲的最长时间。
4、unit(TimeUnit)
第三个参数即keepAliveTime的时间单位
5、workQueue(BlockingQueue)
队列,即当线程数量小于任务数量时,任务存放的队列,源码中提供了三种策略,分别为SynchronousQueue、LinkedBlockingQueue、ArrayBlockingQueue;
(1)、SynchronousQueue
该队列下,当任务将任务交给线程如果没有线程可以立即执行任务时,会创建一个新的线程来执行任务,所以该策略通常需要maxnumPoolSize无限制,以避免任务执行失败。
(2)、LinkedBlockingQueue
无界队列(也可自己指定队列大小),在该队列下,当线程池中的corePoolSize数量的线程均在执行任务时,任务会在队列中等待,不会继续创建线程,即maxnumPoolSize不会再起作用。
(3)、ArrayBlockingQueue
有界队列,在该队列下,队列的大小需要和maxnumPoolSize相互协调,当队列size较大而maxnumPoolSize较小时,可能导致任务排队堆积,不能及时处理,而当队列size较小时则需要较大的maxnumPoolSize以防止新任务不能进入队列排队.
6、threadFactory(ThreadFactory)
顾名思义,即当线程池需要创建一个新的线程时使用的工厂。
7、handler(RejectedExecutionHandler)
reject拒绝,当线程池线程数量达到maxnumPoolSize并且队列饱和时,新任务将无法继续排队等待并抛出RejectedExecutionException,该参数即为相应的处理方式。
ThreadPoolExecutor提供了四种(四个内部类)预定的处理策略:
(1)、AbortPolicy
从源码中可见其直接抛出了异常,
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
(2)、CallerRunsPolicy
源码如下:
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
其调用了Runnable的run()方法,即使用当前线程来执行任务。
(3)、DiscardPolicy
源码如下:
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
什么都没有做,也就是简单的删除了该任务而已。
(4)、DiscardOldestPolicy
源码如下:
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
可以看出其将队列头部的元素进行了删除,然后重试执行(可能重复)。
(二)、构造方法分析
ThreadPoolExecutor的构造方法主要是针对以上参数构建,此处不再赘述。
(三)、钩子方法
ThreadPoolExecutor提供了一些钩子方法用于操纵执行环境,如beforeExecute,afterExecute可在任务执行前或执行后做一些操作。terminated()也可以被覆盖重写,以便在程序终止时做一些特殊处理。
二、ScheculedThreadPoolExecutor分析
该类继承了ThreadPoolExrcutor并实现了ScheduleExecutorService接口,官方给的解释是:
该类可以用来调度在给定延迟时间后执行任务或者周期性执行,优选于Timer(只有一个后台线程),可以通过构造函数类指定后台线程个数。
延迟任务的执行时间是没有任何实时保证的,虽然队列遵循先进先出原则,但是线程间是存在竞争关系的。
默认情况下提交的任务在被执行前取消是不会从队列中删除的,可以通过setRemoveOnCancelPolicy(boolean)方法将其从队列中删除。
该类虽然继承了ThreadPoolExecutor,但是其继承的一些调优方法并没有用(通过构造方法来解释) 。
(一)、构造方法详解
1、ScheduledThreadPoolExecutor(int corePoolSize)
源码如下:
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
可以看出其相当于new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue());
2、ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory)
源码如下:
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), threadFactory);
}
即相当于new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue(), threadFactory);
3、ScheduledThreadPoolExecutor(int corePoolSize,RejectedExecutionHandler handler)
源码如下:
public ScheduledThreadPoolExecutor(int corePoolSize,
RejectedExecutionHandler handler) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), handler);
}
即相当于new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue(), handler);
4、ScheduledThreadPoolExecutor(int corePoolSize,ThreadFactory threadFactory,RejectedExecutionHandler handler)
源码如下:
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), threadFactory, handler);
}
即相当于new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue(), threadFactory, handler);
**从以上构造方法可以看出,创建SchduledThreadPoolExecutor时只能对corePoolSize,threadFactory,handler三个参数进行操作,所以ThreadPoolExecutor的一些调优方法对于ScheduledThreadPoolExecutor是没有作用的。**另外以上构造方法中均是使用了其内部类DelayedWorkQueue来作为队列对象,以后再分析DelayedWorkQueue吧。
三、Executors分析
Executors提供了一系列创建线程池的静态方法。
(一)、newFixedThreadPool(int nThread)
源码如下:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
相当于创建了一个corePoolSize=maxnumPoolSize的ThreadPoolExecutor对象,队列使用new LinkedBlockingQueue,且默认size为Interger.MAX_VALUE
(二)、newSingleThreadExecutor()
源码如下:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
相当于创建了一个corePoolSize=maxnumPoolSize=1的ThreadPoolExecutor对象,队列使用new LinkedBlockingQueue,且默认size为Interger.MAX_VALUE
(三)、newCachedThreadPool()
源码如下:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
创建一个corePoolSize为0,但是maxnumPoolSize为Integer.MZX_VALUE,过期时间为60秒,使用SynchronousQueue做为队列对象的ThreadPoolExecutor。
以上三个静态方法返回对象均ThreadPoolExecutor,只是其参数不同,且均可添加ThreadFactory参数来指定创建线程的工厂。
(四)、ScheduledThreadPool
针对ScheduledThreadPool,Executors提供了以下四种方法:
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1));
}
public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1, threadFactory));
}
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public static ScheduledExecutorService newScheduledThreadPool(
int corePoolSize, ThreadFactory threadFactory) {
return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}