ThreadPoolExecutor机制(一)--基本介绍

来源:互联网 发布:你瞒我瞒网络链接 编辑:程序博客网 时间:2024/06/05 16:11

一.概述

●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 staticExecutorServicenewFixedThreadPool(intnThreads) {
    return newThreadPoolExecutor(nThreads,nThreads,
                                  0L,TimeUnit.MILLISECONDS,
                                  newLinkedBlockingQueue<Runnable>());
}

●构造一个缓冲功能的线程池,配置corePoolSize = 0,maximumPoolSize = Integer.MAX_VALUE,keepAliveTime = 60s,以及一个无容量的阻塞队列SynchronousQueue,因此任务提交之后,将会创建新的线程执行,线程空闲超过60s将会销毁。

public staticExecutorServicenewCachedThreadPool() {
    return newThreadPoolExecutor(0,Integer.MAX_VALUE,
                                  60L,TimeUnit.SECONDS,
                                  newSynchronousQueue<Runnable>());
}

●构造一个只支持一个线程的线程池,配置corePoolSize=maximumPoolSize=1,无界阻塞队列LinkedBlockingQueue;保证任务由一个线程串行执行

public staticExecutorServicenewSingleThreadExecutor() {
    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,所以最好异步开个线程获取结果

0 0