Skip to content
Go back

ThreadPoolExecutor的重要特性和概念

Published:  at  08:23 PM

核心和最大线程数(Core and maximum pool sizes)

ThreadPoolExecutor 会根据指定的 corePoolSizemaximunPoolSize 自动调整当前线程池内线程数量(通过 getPoolSize 可以获取当前线程数量)。 值得注意的是:当 corePoolSize 大于当前线程数,即使当前存在空闲的线程,ThreadPoolExecutor 也会创建一个新的线程来处理新加入的任务。 之后只有在当前线程数介于 corePoolSizemaximunPoolSize 之间并且队列满了之后,ThreadPoolExecutor 才会再创建新的线程。
一般情况下,核心和最大线程数会在构造线程池对象的时候指定,但是也可以通过 setCorePoolSizesetMaximunPoolSize 来动态指定。

预先启动线程

默认情况下,核心线程会在初始阶段就构建,但是在当新任务到达之后才会启动。 可以通过覆盖 prestartCoreThreadprestartAllCoreThreads 方法来改变默认行为来预先启动线程。

线程工厂

ThreadPoolExecutor 默认使用的线程工厂创建出的线程是:在同一个 ThreadGroup 中的,NORM_PRIORITY 优先级的,非守护(non-daemon status)的。

线程存活时间

在当前线程数大于 corePoolSize 的时候,超过该数量的线程会在空闲状态超过指定的 keepAliveTime 时间后终止。 线程的存活时间可以通过 setKeepAliveTime 动态指定。 默认该存活规则只适用于超出核心线程数的额外线程,但可以通过 allowCoreThreadTimeOut 来应用至核心线程。

阻塞队列

情形优先行为
当前线程数 < 核心线程数优先添加新线程
核心线程数 <= 当前线程数 <= 最大线程数优先放置在队列中
核心线程数 <= 当前线程数优先添加新线程
最大线程数 <= 核心线程数执行拒接策略

拒绝策略

当线程池已经关闭 或者 任务数超过队列容量和最大线程数 时,会执行拒绝策略

预定义的拒绝策略有:

策略行为
ThreadPoolExecutor.AbortPolicy抛出 RejectedExecutionException 异常
ThreadPoolExecutor.CallerRunsPolicy调用 execute 的线程执行该任务(提供了一个被压策略,减缓任务的提交速率)
ThreadPoolExecutor.DiscardPolicy丢弃任务新任务
ThreadPoolExecutor.DiscardOldestPolicy在线程池未关闭的情况下,丢弃队列头最老的任务,并再次尝试执行(可能执行失败,导致再次重复该策略)

Hook方法

线程池任务执行相关的生命周期方法,适用于一些场景的功能增强:刷新ThreadLocal工具状态,聚合统计,日志等等

方法解释
beforeExecute执行任务之前
afterExecute执行任务之后
terminated线程池完全关闭之后

注意这些hook方法如果抛出异常可能导致线程池内部线程执行失败或突然终止。

维护队列

可以直接使用 getQueue 接口来对任务队列进行监控或者调试。 如果有大量任务在队列中,可以调用 removepurge 接口来帮助回收存储空间

线程池回收

线程池在应用中不被引用 并且 线程池内也没有剩余线程,那么线程池会自动关闭。 该特性可以配合 allowCoreThreadTimeOut 使得在不显式调用 shutdowm 接口时,可以自动关闭,回收资源。


Suggest Changes

Previous Post
linux中分析CPU占用情况
Next Post
为什么重写object的finalize方法后,使用PhantomReference似乎未监听到对象的回收?