本文主要是介绍ExecutorService引发的血案(三)ThreadPoolExecutor,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
前面我们提到了ExecutorService结构中的一个工厂类,Executors。这个类提供了一系列构造ExecutorService实例的方法。
这些方法的核心就是两个类,分别是 ThreadPoolExecutor
和 ScheduledThreadPoolExecutor
类。(当然还有别的类,比较常用的就是这两个)
今天介绍的就是 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
corePoolSize
和 maximumPoolSize
这两个参数相当重要,他的值决定了当一个task执行的时候,thread 是如何分配的。
下面这张图大概的介绍了,当一个新task 由 ThreadPoolExecutor执行的时候内部运行的情况。
图中提到的 “根据corePoolSize
和 maximumPoolSize
判断”,就是根据 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的值是一样的。
这篇关于ExecutorService引发的血案(三)ThreadPoolExecutor的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!