其他分享
首页 > 其他分享> > 线程池之ThreadPoolExecutor概述

线程池之ThreadPoolExecutor概述

作者:互联网

线程池解决了两个不同的问题:

 为了在广泛的上下文中有用,此类提供了许多可调参数和可扩展性钩子。 但是,在常见场景中,我们预配置了几种线程池,我们敦促程序员使用更方便的Executors的工厂方法直接使用。

注:这里没有提到ScheduledExecutorService ,后续解析。

一、Core and maximum pool sizes 核心和最大线程池数量

参数翻译
corePoolSize 核心线程池数量
maximumPoolSize 最大线程池数量

线程池执行器将会根据corePoolSize和maximumPoolSize自动地调整线程池大小。

当在execute(Runnable)方法中提交新任务并且少于corePoolSize线程正在运行时,即使其他工作线程处于空闲状态,也会创建一个新线程来处理该请求。 如果有多于corePoolSize但小于maximumPoolSize线程正在运行,则仅当队列已满时才会创建新线程。   通过设置corePoolSize和maximumPoolSize相同,您可以创建一个固定大小的线程池。 通过将maximumPoolSize设置为基本上无界的值,例如Integer.MAX_VALUE,您可以允许池容纳任意数量的并发任务。 通常,核心和最大池大小仅在构建时设置,但也可以使用setCorePoolSizesetMaximumPoolSize进行动态更改。 这段话详细了描述了线程池对任务的处理流程,这里用个图总结一下

 

 二、prestartCoreThread 核心线程预启动

在默认情况下,只有当新任务到达时,才开始创建和启动核心线程, 但是我们可以使用 prestartCoreThread()prestartAllCoreThreads() 方法动态调整。
如果使用非空队列构建池,则可能需要预先启动线程。
方法作用
prestartCoreThread() 创一个空闲任务线程等待任务的到达
prestartAllCoreThreads() 创建核心线程池数量的空闲任务线程等待任务的到达

三、ThreadFactory 线程工厂

新线程使用ThreadFactory创建。 如果未另行指定,则使用Executors.defaultThreadFactory默认工厂,使其全部位于同一个ThreadGroup中,并且具有相同的NORM_PRIORITY优先级和非守护进程状态。 通过提供不同的ThreadFactory,您可以更改线程的名称,线程组,优先级,守护进程状态等。

四、Keep-alive times 线程存活时间

如果线程池当前拥有超过corePoolSize的线程,那么多余的线程在空闲时间超过keepAliveTime时会被终止 ( 请参阅getKeepAliveTime(TimeUnit) )。 这提供了一种在不积极使用线程池时减少资源消耗的方法。 如果池在以后变得更加活跃,则应构建新线程。 也可以使用方法setKeepAliveTime(long,TimeUnit)进行动态调整。

防止空闲线程在关闭之前终止,可以使用如下方法:

setKeepAliveTime(Long.MAX_VALUE,TimeUnit.NANOSECONDS);
默认情况下,keep-alive策略仅适用于存在超过corePoolSize线程的情况。 但是,只要keepAliveTime值不为零,方法allowCoreThreadTimeOut(boolean)也可用于将此超时策略应用于核心线程

五、Queuing 队列

BlockingQueu用于存放提交的任务,队列的实际容量与线程池大小相关联。

主要有三种队列策略:

六、Rejected tasks 拒绝任务

拒绝任务有两种情况:
  1.  线程池已经被关闭;
  2. 任务队列已满且maximumPoolSizes已满;
无论哪种情况,都会调用RejectedExecutionHandler的rejectedExecution方法。预定义了四种处理策略:

七、Hook methods 钩子方法

ThreadPoolExecutor为提供了每个任务执行前后提供了钩子方法, 重写beforeExecute(Thread,Runnable)afterExecute(Runnable,Throwable)方法来操纵执行环境; 例如,重新初始化ThreadLocals,收集统计信息或记录日志等。 此外,terminated()在Executor完全终止后需要完成后会被调用,可以重写此方法,以执行任殊处理。
注意:如果hook或回调方法抛出异常,内部的任务线程将会失败并结束。

八、Queue maintenance 维护队列

getQueue()方法可以访问任务队列,一般用于监控和调试。 绝不建议将这个方法用于其他目的。当在大量的队列任务被取消时,remove()purge()方法可用于回收空间。

九、Finalization 关闭

如果程序中不在持有线程池的引用,并且线程池中没有线程时,线程池将会自动关闭。 如果您希望确保即使用户忘记调用 shutdown()方法也可以回收未引用的线程池,使未使用线程最终死亡。 那么必须通过设置适当的 keep-alive times 并设置allowCoreThreadTimeOut(boolean) 或者 使 corePoolSize下限为0 。
一般情况下,线程池启动后建议手动调用shutdown()关闭。

https://www.jianshu.com/p/c41e942bcd64

标签:队列,maximumPoolSize,corePoolSize,任务,概述,线程,方法,ThreadPoolExecutor
来源: https://www.cnblogs.com/Vincent-yuan/p/14984454.html