一.概述
●ThreadPoolExecutor座位java.util.concurrent包对外提供的基础实现,以内部线程池的形式对外提供管理任务执行,线程调度,线程池管理等等服务。
●Executors方法提供的线程服务,都是通过参数来实现不同的线程池机制。
二.构造方法讲解
●共有4个构造方法,代码如下:
publicThreadPoolExecutor(intcorePoolSize,
intmaximumPoolSize,
longkeepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize,maximumPoolSize,keepAliveTime,unit,workQueue,
Executors.defaultThreadFactory(),defaultHandler);
}
publicThreadPoolExecutor(intcorePoolSize,
intmaximumPoolSize,
longkeepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize,maximumPoolSize,keepAliveTime,unit,workQueue,
threadFactory,defaultHandler);
}
publicThreadPoolExecutor(intcorePoolSize,
intmaximumPoolSize,
longkeepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize,maximumPoolSize,keepAliveTime,unit,workQueue,
Executors.defaultThreadFactory(),handler);
}
publicThreadPoolExecutor(intcorePoolSize,
intmaximumPoolSize,
longkeepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if(corePoolSize <
0 ||
maximumPoolSize <=0
||
maximumPoolSize < corePoolSize ||
keepAliveTime <0)
throw newIllegalArgumentException();
if (workQueue ==null
|| threadFactory ==null
|| handler ==null)
throw newNullPointerException();
this.corePoolSize=
corePoolSize;
this.maximumPoolSize=
maximumPoolSize;
this.workQueue=
workQueue;
this.keepAliveTime=
unit.toNanos(keepAliveTime);
this.threadFactory=
threadFactory;
this.handler=
handler;
}
●构造方法参数讲解:
corePoolSize 核心线程池大小
maximumPoolSize 最大线程池大小
keepAliveTime 线程池中超过corePoolSize数目的空闲线程最大存活时间;可以allowCoreThreadTimeOut(true)使得核心线程有效时间也为keepAliveTime
TimeUnit keepAliveTime时间单位
workQueue 阻塞任务队列
threadFactory 新建线程工厂
RejectedExecutionHandler 当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来处理
●参数重点讲解
主要是corePoolSize,maximumPoolSize,workQueue之间关系讲解
①当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。
②当线程池达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行
③当workQueue已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务
④当提交任务数超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理
⑤当线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程,知道当前线程数等于corePoolSize
⑥当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭
三.Executors 提供的线程池配置方案
●构造一个固定线程池数目的线程池,配置的corePoolSize与maximumPoolSize相同,同时使用了一个无界的LinkedBlockingQueue存放阻塞任务,因此多余的任务将存在阻塞队列,不会交由RejectedExecutionHandler处理
public staticExecutorService
newFixedThreadPool(intnThreads)
{
return newThreadPoolExecutor(nThreads,nThreads,
0L,TimeUnit.MILLISECONDS,
newLinkedBlockingQueue<Runnable>());
}
●构造一个缓冲功能的线程池,配置corePoolSize = 0,maximumPoolSize = Integer.MAX_VALUE,keepAliveTime = 60s,以及一个无容量的阻塞队列SynchronousQueue,因此任务提交之后,将会创建新的线程执行,线程空闲超过60s将会销毁。
public staticExecutorService
newCachedThreadPool() {
return newThreadPoolExecutor(0,Integer.MAX_VALUE,
60L,TimeUnit.SECONDS,
newSynchronousQueue<Runnable>());
}
●构造一个只支持一个线程的线程池,配置corePoolSize=maximumPoolSize=1,无界阻塞队列LinkedBlockingQueue;保证任务由一个线程串行执行
public staticExecutorService
newSingleThreadExecutor() {
return newFinalizableDelegatedExecutorService
(newThreadPoolExecutor(1,1,
0L,TimeUnit.MILLISECONDS,
newLinkedBlockingQueue<Runnable>()));
}
●构造有定时功能的线程池,配置corePoolSize,无界延迟阻塞队列DelayedWorkQueue;有意思的是:maximumPoolSize=Integer.MAX_VALUE,由于DelayedWorkQueue是无界队列,所以这个值是没有意义的
public staticScheduledExecutorServicenewScheduledThreadPool(intcorePoolSize)
{
return newScheduledThreadPoolExecutor(corePoolSize);
}
public classScheduledThreadPoolExecutor
extendsThreadPoolExecutor
implementsScheduledExecutorService
四.总结:
1、用ThreadPoolExecutor自定义线程池,看线程是的用途,如果任务量不大,可以用无界队列,如果任务量非常大,要用有界队列,防止OOM
2、如果任务量很大,还要求每个任务都处理成功,要对提交的任务进行阻塞提交,重写拒绝机制,改为阻塞提交。保证不抛弃一个任务
3、最大线程数一般设为2N+1最好,N是CPU核数
4、核心线程数,看应用,如果是任务,一天跑一次,设置为0,合适,因为跑完就停掉了,如果是常用线程池,看任务量,是保留一个核心还是几个核心线程数
5、如果要获取任务执行结果,用CompletionService,但是注意,获取任务的结果的要重新开一个线程获取,如果在主线程获取,就要等任务都提交后才获取,就会阻塞大量任务结果,队列过大OOM,所以最好异步开个线程获取结果