ExecutorService引发的血案(三)ThreadPoolExecutor

前面我们提到了ExecutorService结构中的一个工厂类,Executors。这个类提供了一系列构造ExecutorService实例的方法。
这些方法的核心就是两个类,分别是 ThreadPoolExecutorScheduledThreadPoolExecutor 类。(当然还有别的类,比较常用的就是这两个)

今天介绍的就是 ThreadPoolExecutor

简介

这个类 的包名 java.util.concurrent.ThreadPoolExecutor 它当然也实现了 ExecutorService 接口

参照官网链接的描述:链接

ExecutorService 在 执行每一个提交的task的时候都是使用线程池内的线程来完成,而且 ExecutorService在配置的时候大部分都是使用Executors提供的方法。

线程池解决了两个不同的问题:
1.他通过(reduced per-task invocation overhead “简化的什么…… 实在不会翻译”)方法,提升了在执行大量异步任务时的性能。
2.他提供了一系列管理资源的方法,包括线程,当在执行异步任务的时候就会开始消耗资源。(当然ThreadPoolExecutor自身也会持有一些静态变量)

在ThreadPoolExecutor的构造方法中,提供了一些参数。这些参数可以根据我们不同的需求来进行对应的配置。 但是官方还是希望我们使用 Executors中提供的工厂方法,这样更加方便,这些提前配置好的方法能够满足大部分的使用场景,但是通过一些配置参数也是可以完成私人定制的。

私人定制

既然是私人定制就不得不提到其中的参数。

int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue< Runnable > workQueue)
Core and maximum pool sizes

corePoolSizemaximumPoolSize

这两个参数相当重要,他的值决定了当一个task执行的时候,thread 是如何分配的。

这里写图片描述

下面这张图大概的介绍了,当一个新task 由 ThreadPoolExecutor执行的时候内部运行的情况。

图中提到的 “根据corePoolSizemaximumPoolSize 判断”,就是根据 running thread 的数量判断,下面我们来分析使用。

(1) 运行状态线程 < corePoolSize
“fewer than corePoolSize threads are running”

当一个新的task通过 `execute`方法提交之后,如果这时 ThreadPoolExecutor中 "运行线程"的数量 满足 条件

那么ThreadPoolExecutor会新开线程来执行这个任务,即使存在其他的 闲置线程(idle)没有使用。

(2) 运行状态线程 >= corePoolSize && 运行状态线程 < maximumPoolSize (并且 queue not full )
“more than corePoolSize but less than maximumPoolSize”

如果处于(2)这种条件,那么新的task将会进入queue中,

(3) 在满足(2)的前提下,queue is full (队列已经满了)

如果处于(3)这种条件,那么新的task进来,就会new Thread来执行新的task。

(4)queue is full && 运行状态线程 >=maximumPoolSize

如果处于(4)这种条件,那么新进来 task 直接会被 reject。这个task是无法得到执行的。

(5)

这里其实也要注意一点,那就是Queue的类型,如果Queue是有界的,当然就会出现上面的四种情况。

但是如果 Queue是 无界的(不存在full)那么 `运行状态线程`  是永远也不会超过 corePoolSize 的值。
keepAliveTime

这个参数负责当前 ThreadPoolExecutor 管理的 Thread 能够存活的时间。

管理方法:
如果当前线程池中 运行状态线程 >corePoolSize,那么 其他处于 idle状态,并且存活时间 >keepAliveTime 线程就会被 终结。

这个参数在线程池处于不是很活跃的状态的时候可以有效地节约 资源的消耗。

BlockingQueue

这个容器 就是用来存放Task的,一般分为三个种类, 后面的文章会介绍到。

On-demand construction

除了这些构造函数能够初始化以外,还有一些特殊的方法能够进行初始化。

prestartCoreThread()

prestartAllCoreThreads()

工厂方法:

Executors.newCachedThreadPool()

这个方法构建了一个 无界的线程池,它会自动完成线程的回收。

 /**
     * Creates a thread pool that creates new threads as needed, but
     * will reuse previously constructed threads when they are
     * available.  These pools will typically improve the performance
     * of programs that execute many short-lived asynchronous tasks.
     * Calls to {@code execute} will reuse previously constructed
     * threads if available. If no existing thread is available, a new
     * thread will be created and added to the pool. Threads that have
     * not been used for sixty seconds are terminated and removed from
     * the cache. Thus, a pool that remains idle for long enough will
     * not consume any resources. Note that pools with similar
     * properties but different details (for example, timeout parameters)
     * may be created using {@link ThreadPoolExecutor} constructors.
     *
     * @return the newly created thread pool
     */
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

我们看出 maximumPoolSize 这个参数给的是 无穷大。至于Queue的选择,后面的文章会讲述Queue。

Executors.newSingleThreadExecutor()

这个方法构建了一个单线程的调度机制

 /**
     * Creates an Executor that uses a single worker thread operating
     * off an unbounded queue. (Note however that if this single
     * thread terminates due to a failure during execution prior to
     * shutdown, a new one will take its place if needed to execute
     * subsequent tasks.)  Tasks are guaranteed to execute
     * sequentially, and no more than one task will be active at any
     * given time. Unlike the otherwise equivalent
     * {@code newFixedThreadPool(1)} the returned executor is
     * guaranteed not to be reconfigurable to use additional threads.
     *
     * @return the newly created single-threaded Executor
     */
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
Executors.newFixedThreadPool

这个方法实现了固定线程数量的线程池

  /**
     * Creates a thread pool that reuses a fixed number of threads
     * operating off a shared unbounded queue, using the provided
     * ThreadFactory to create new threads when needed.  At any point,
     * at most {@code nThreads} threads will be active processing
     * tasks.  If additional tasks are submitted when all threads are
     * active, they will wait in the queue until a thread is
     * available.  If any thread terminates due to a failure during
     * execution prior to shutdown, a new one will take its place if
     * needed to execute subsequent tasks.  The threads in the pool will
     * exist until it is explicitly {@link ExecutorService#shutdown
     * shutdown}.
     *
     * @param nThreads the number of threads in the pool
     * @param threadFactory the factory to use when creating new threads
     * @return the newly created thread pool
     * @throws NullPointerException if threadFactory is null
     * @throws IllegalArgumentException if {@code nThreads <= 0}
     */
    public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
    }

可以看到 corePoolSize 和 maximumPoolSize的值是一样的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值