Java配置线程池

2023-05-24 18:01:28 来源:博客园
一、Java配置线程池1、线程池分类、其他1.1、分类

IO密集型 和 CPU密集型任务的特点不同,因此针对不同类型的任务,选择不同类型的线程池可以获得更好的性能表现。


(相关资料图)

1.1. IO密集型任务

​IO密集型任务的特点是需要频繁读写磁盘、网络或者其他IO资源,执行时间长,CPU占用率较低。

对于这类任务,线程的执行时间主要取决于IO操作的速度,而非CPU的执行能力。

​因此,线程池的线程数应该设置较大,以便充分利用IO资源。

通常建议使用CachedThreadPool线程池或者FixedThreadPool线程池来处理IO密集型任务。

1.2. CPU密集型任务

​CPU密集型任务的特点是需要进行大量的计算,执行时间长,CPU占用率较高。

对于这类任务,线程的执行时间主要取决于CPU的执行能力。

​因此,线程池的线程数应该设置较小,以充分利用CPU的计算能力,避免过多的线程切换和上下文切换导致的性能损失。

通常建议使用FixedThreadPool线程池或者SingleThreadPool线程池来处理CPU密集型任务。

总之,选择恰当的线程池类型可以充分发挥不同类型任务的性能,提高程序效率和响应速度。

1.2. 异步线程池的选择
对于异步线程池,通常建议使用IO密集型线程池。异步任务通常是网络IO或磁盘IO等操作,这些操作的执行时间相对于CPU计算的执行时间要长得多。使用IO密集型线程池可以更好地利用IO资源,提高多个异步任务的执行效率和吞吐量,同时避免由于过多的线程切换和上下文切换导致的性能损失。
1.3. 线程池工作步奏

很多任务——》线程池创建核心线程——》任务超过最大线程——》把任务放入队列中等待执行——》队列中放满了——》进入处理策略

2、线程池参数、合理参数2.1、参数①、核心线程数
当线程池中的线程数量为 corePoolSize核心线程数 时,即使这些线程处于空闲状态,也不会销毁(除非设置 allowCoreThreadTimeOut=true)。//  -> 核心线程,也就是正在处理中的任务//  -> 虽然 CPU 核心数可以作为线程池中线程数量的参考指标,但最终线程数量还需要根据具体情况进行设置和调整。//  -> 如果同时运行的线程数量超过 CPU 核心数,就会发生--线程上下文切换--,导致额外的开销和性能下降。所以线程不能创建得过多
②、最大线程数
线程池中允许的线程数量的最大值。        //  -> 当线程数 = maxPoolSize最大线程数时,还有新任务,就会放进队列中等待执行 ↓↓↓
③、队列长度
当核心线程数达到最大时,新任务会放在队列中排队等待执行        //  -> 根据业务配置,如果队列长度过大,可能会导致系统内存资源占用过高,最终导致 OOM,需要注意控制        //  -> 如果需要执行的任务装满了队列,就会走拒绝策略 ↓↓↓
④、拒绝策略
(官方提供4种,也可以自定义):因达到线程边界和任务队列满时,针对新任务的处理方法。        // -> AbortPolicy:直接丢弃任务并抛出 RejectedExecutionException 异常。(默认策略)        // -> DiscardPolicy:直接丢弃掉,不会抛出异常        // -> DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)        // -> CallerRunsPolicy:交给主线程(调用线程)去执行
⑤、空闲线程存活时间
(默认60s):设置当前线程池中空闲线程的存活时间,即线程池中的线程如果有一段时间没有任务可执行,则会被回收掉。        //  -> 当线程池中的线程数大于 corePoolSize 时,多余的空闲线程将在销毁之前等待新任务的最长时间。        //  -> 如果一个线程在空闲时间超过了 keepAliveSeconds,且当前线程池中线程数量大于 corePoolSize,则该线程将会被回收;        //  -> 核心线程会一直存活,除非线程池被关闭 或 设置下面的参数        //  -> 如果 AllowCoreThreadTimeout设置为true,核心线程也会被回收,直到线程池中的线程数降为 0。        //     但如果线程池中有任务在执行,那么空闲线程就会一直保持存活状态,直到任务执行完毕。        //  -> 该方法的使用可以将线程池的空闲线程回收,以减少资源占用,同时也能保证线程池中始终有可用的线程来执行任务,提高线程池的效率。
⑥、是否禁止线程池自动终止空闲的核心线程
为 true 时,空闲的核心线程会在 keepAliveTime 时间后被回收,并且在后续任务到来时需要重新创建线程来执行任务。        // 为 false 时,线程池中的核心线程不会被回收,即使它们处于空闲状态一段时间。        //  -> 在线程池创建时,就会预先创建核心线程数的线程,这些线程将一直存在,除非线程池被关闭或重新配置。
⑦、当前线程池的等待时间
指等待所有任务执行完毕后线程池的最长时间。300秒 = 5分钟        // -> 当所有任务执行完毕后,线程池会等待一段时间(即等待时间),来确保所有任务都已经完成。        // -> 如果在等待时间内所有任务仍未完成,则线程池会强制停止,以确保任务不会无限制地执行下去。
⑧、当前线程池是否在关闭时等待所有任务执行完成
// -> 可以确保所有任务都执行完毕后才关闭线程池,避免任务被丢弃,同时也确保线程池可以正常结束,释放资源。        // -> 为 true 时,线程池在关闭时会等待所有任务都执行完成后再关闭        // -> 为 false 时,线程池会直接关闭,未执行完成的任务将被丢弃。
⑨、线程名称前缀
// 9线程前缀名称        executor.setThreadNamePrefix("myIo-Th-Pool-");        // 初始化        executor.initialize();
2.2、合理配置

①线程数量:N = 计算机cpu数量

如果同时运行的线程数量超过 CPU 核心数,就会发生--线程上下文切换--,导致额外的开销和性能下降。所以线程不能创建得过多一般的配置如下:也可以通过计算获取。
* IO密级 :2 * N     * CPU密级:1 + N

②队列长度:

如果队列长度过大,可能会导致系统内存资源占用过高,最终导致 OOM,需要注意控制根据自身业务配置3、配置3.1、配置线程池的Bean的选择

配置线程池选择:ThreadPoolTaskExecutor(Spring项目推荐),还是选择ThreadPoolExecutor?

ThreadPoolTaskExecutor是 Spring 框架中对 Java 自带的线程池 ThreadPoolExecutor 进行了封装和扩展,并增加了一些优化和功能。通常来说,如果你使用 Spring 框架,需要使用线程池,那么建议使用 ThreadPoolTaskExecutor。 ThreadPoolTaskExecutor 提供了更多的配置选项,例如线程池的最大线程数、核心线程数、缓冲队列大小、线程命名前缀、线程池饱和策略等等,同时可以方便地集成到 Spring 应用中。另外,ThreadPoolTaskExecutor 还能够支持异步执行任务,使用方便。 相比之下,ThreadPoolExecutor 是 Java 自带的线程池实现类,提供了基本的线程池功能,但没有 ThreadPoolTaskExecutor 提供的更多配置选项和功能。如果你不使用 Spring 框架,或者使用 Spring 框架但不需要使用其提供的线程池实现,那么可以考虑使用 ThreadPoolExecutor。

综上所述,选择使用 ThreadPoolTaskExecutor 还是 ThreadPoolExecutor 取决于具体的业务需求和技术栈,可以根据实际情况进行选择。

3.2、获取当前电脑(服务器)的核心线程数
int N = Runtime.getRuntime().availableProcessors()
3.3、IO密集型
package com.cc.md.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.scheduling.annotation.EnableAsync;import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.ThreadPoolExecutor;/** IO型的线程池 * 
  • IO密集型配置线程数经验值是:2N (CPU核数*2)
  • *
  • 异步线程池:建议用io密集型:
  • * 对于异步线程池,通常建议使用IO密集型线程池。 * 异步任务通常是网络IO或磁盘IO等操作,这些操作的执行时间相对于CPU计算的执行时间要长得多。 * 使用IO密集型线程池可以更好地利用IO资源,提高多个异步任务的执行效率和吞吐量, * 同时避免由于过多的线程切换和上下文切换导致的性能损失。 * @author CC * @since 2023/5/23 0023 */@Configuration@EnableAsyncpublic class IoThreadPool { /** 线程数量 * CUP数量:N = Runtime.getRuntime().availableProcessors() * IO密级:2 * N * CPU密级:1 + N */ public static final int THREAD_SIZE = 2 * (Runtime.getRuntime().availableProcessors()); /** * 队列大小 */ public static final int QUEUE_SIZE = 1000; @Bean(name = "myIoThreadPool") public ThreadPoolTaskExecutor threadPoolExecutor(){ //配置线程池选择:ThreadPoolTaskExecutor,还是选择ThreadPoolExecutor好些? // -> ThreadPoolTaskExecutor 是 Spring 框架中对 Java 自带的线程池 ThreadPoolExecutor 进行了封装和扩展, // 并增加了一些优化和功能。通常来说,如果你使用 Spring 框架,需要使用线程池,那么建议使用 ThreadPoolTaskExecutor。 ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 1核心线程数:当线程池中的线程数量为 corePoolSize 时,即使这些线程处于空闲状态,也不会销毁(除非设置 allowCoreThreadTimeOut=true)。 // -> 核心线程,也就是正在处理中的任务 // -> 虽然 CPU 核心数可以作为线程池中线程数量的参考指标,但最终线程数量还需要根据具体情况进行设置和调整。 // -> 如果同时运行的线程数量超过 CPU 核心数,就会发生--线程上下文切换--,导致额外的开销和性能下降。所以线程不能创建得过多 executor.setCorePoolSize(THREAD_SIZE); // 2最大线程数:线程池中允许的线程数量的最大值。 // -> 当线程数 = maxPoolSize最大线程数时,还有新任务,就会放进队列中等待执行 ↓↓↓ executor.setMaxPoolSize(THREAD_SIZE); // 3队列长度:当核心线程数达到最大时,新任务会放在队列中排队等待执行 // -> 根据业务配置,如果队列长度过大,可能会导致系统内存资源占用过高,最终导致 OOM,需要注意控制 // -> 如果需要执行的任务装满了队列,就会走拒绝策略 ↓↓↓ executor.setQueueCapacity(QUEUE_SIZE); // 4拒绝策略(官方提供4种,也可以自定义):因达到线程边界和任务队列满时,针对新任务的处理方法。 // -> AbortPolicy:直接丢弃任务并抛出 RejectedExecutionException 异常。(默认策略) // -> DiscardPolicy:直接丢弃掉,不会抛出异常 // -> DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程) // -> CallerRunsPolicy:交给主线程(调用线程)去执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy()); // 5空闲线程存活时间(默认60s):设置当前线程池中空闲线程的存活时间,即线程池中的线程如果有一段时间没有任务可执行,则会被回收掉。 // -> 当线程池中的线程数大于 corePoolSize 时,多余的空闲线程将在销毁之前等待新任务的最长时间。 // -> 如果一个线程在空闲时间超过了 keepAliveSeconds,且当前线程池中线程数量大于 corePoolSize,则该线程将会被回收; // -> 核心线程会一直存活,除非线程池被关闭 或 设置下面的参数 // -> 如果 AllowCoreThreadTimeout设置为true,核心线程也会被回收,直到线程池中的线程数降为 0。 // 但如果线程池中有任务在执行,那么空闲线程就会一直保持存活状态,直到任务执行完毕。 // -> 该方法的使用可以将线程池的空闲线程回收,以减少资源占用,同时也能保证线程池中始终有可用的线程来执行任务,提高线程池的效率。 executor.setKeepAliveSeconds(60); //6是否禁止线程池自动终止空闲的核心线程。 // 为 true 时,空闲的核心线程会在 keepAliveTime 时间后被回收,并且在后续任务到来时需要重新创建线程来执行任务。 // 为 false 时,线程池中的核心线程不会被回收,即使它们处于空闲状态一段时间。 // -> 在线程池创建时,就会预先创建核心线程数的线程,这些线程将一直存在,除非线程池被关闭或重新配置。 executor.setAllowCoreThreadTimeOut(true); // 7当前线程池的等待时间:指等待所有任务执行完毕后线程池的最长时间。300秒 = 5分钟 // -> 当所有任务执行完毕后,线程池会等待一段时间(即等待时间),来确保所有任务都已经完成。 // -> 如果在等待时间内所有任务仍未完成,则线程池会强制停止,以确保任务不会无限制地执行下去。 executor.setAwaitTerminationSeconds(300); // 8当前线程池是否在关闭时等待所有任务执行完成 // -> 可以确保所有任务都执行完毕后才关闭线程池,避免任务被丢弃,同时也确保线程池可以正常结束,释放资源。 // -> 为 true 时,线程池在关闭时会等待所有任务都执行完成后再关闭 // -> 为 false 时,线程池会直接关闭,未执行完成的任务将被丢弃。 executor.setWaitForTasksToCompleteOnShutdown(true); // 9线程前缀名称 executor.setThreadNamePrefix("myIo-Th-Pool-"); // 初始化 executor.initialize(); return executor; }}
    3.4、CPU密集型
    package com.cc.md.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.ThreadPoolExecutor;/** CPU型的线程池 * @author CC * @since 2023/5/23 0023 */@Configurationpublic class CpuThreadPool {    /** 线程数量     * CUP数量:N = Runtime.getRuntime().availableProcessors()     * IO密级:2 * N     * CPU密级:1 + N     */    public static final int THREAD_SIZE = 1 + (Runtime.getRuntime().availableProcessors());    /**     * 队列大小     */    public static final int QUEUE_SIZE = 1000;    @Bean(name = "myCpuThreadPool")    public ThreadPoolTaskExecutor threadPoolExecutor(){        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();        executor.setCorePoolSize(THREAD_SIZE);        executor.setMaxPoolSize(THREAD_SIZE);        executor.setQueueCapacity(QUEUE_SIZE);        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());        executor.setKeepAliveSeconds(60);        executor.setAllowCoreThreadTimeOut(true);        executor.setAwaitTerminationSeconds(300);        executor.setWaitForTasksToCompleteOnShutdown(true);        executor.setThreadNamePrefix("myCpu-T-Pool-");        executor.initialize();        return executor;    }}
    4、参考

    https://zhuanlan.zhihu.com/p/112527671

    https://blog.csdn.net/shang_0122/article/details/120777113

    https://blog.csdn.net/zhuimeng_by/article/details/107891268

    https://blog.csdn.net/qq_25720801/article/details/129559164

    https://blog.csdn.net/riemann_/article/details/104704197

    关键词:

    相关文章

    热文推荐

    Java配置线程池
    Java配置线程池

    一、Java配置线程池 1、线程池==分类==、其他 ......更多>

    名医专家争当健康领跑员 助力全民健康素养提升
    名医专家争当健康领跑员 助力全民健康素养提升

    5月23日,“健康中国我们行动--2023健康传播推动健康......更多>

    实时焦点:“2种旧东西,再穷也不留”如果家里有,赶紧处理掉!
    实时焦点:“2种旧东西,再穷也不留”如果家里有,赶紧处理掉!

    “2种旧东西,再穷也不留”如果家里有,赶紧处理掉!......更多>

    海波重科(300517.SZ)控股股东一致行动人张丽完成减持10万股 焦点快播
    海波重科(300517.SZ)控股股东一致行动人张丽完成减持10万股 焦点快播

    智通财经APP讯,海波重科公告,截至2023年5月22日,公......更多>

    排行推荐

    晶科能源:拟将公司持有的新疆晶科100%股权出售给资阳市重大产业股权投资基金合伙企业(有限合伙)及董仕宏共同指定的主体
    晶科能源:拟将公司持有的新疆晶科100%股权出售给资阳市重大产业股权投资基金合伙企业(有限合伙)及董仕宏共同指定的主体
    晶科能源(688223):拟将公司持有的新疆晶科100%股权出... 更多>
    天天快资讯:杭氧股份:为开展氢能源项目战略合作
    天天快资讯:杭氧股份:为开展氢能源项目战略合作
    杭氧股份(002430):为开展氢能源项目战略合作,拟与山... 更多>
    【速看料】大唐发电:天津津能拟减持不超0.97%公司股份
    【速看料】大唐发电:天津津能拟减持不超0.97%公司股份
    大唐发电(601991)5月24日晚间公告,持股6 85%的股东... 更多>
    山东黄金:公司控股子公司金舜矿业以8.66亿元竞得大桥金矿采矿权
    山东黄金:公司控股子公司金舜矿业以8.66亿元竞得大桥金矿采矿权
    山东黄金(600547):公司控股子公司金舜矿业以8 66亿... 更多>
    中工国际:中国中元联合签署深圳机场南航基地一期项目勘察设计合同
    中工国际(002051)5月24日晚间公告,近日,下属全资子... 更多>
    科大讯飞:使用大模型编造虚假信息属于违法行为,公司会借助法律武器保护公司和投资者利益
    科大讯飞(002230)在互动平台表示,使用大模型编造虚假... 更多>
    中国连锁经营协会副会长武瑞玲:零售行业呈现结构性复苏态势
    5月24日,中国连锁经营协会副会长武瑞玲在微盟(2013 ... 更多>
    云路股份:董事拟减持公司不超5.19%股份 世界播报
    云路股份(688190)5月24日晚间公告,持股20 78%的股东... 更多>
    金辰股份:未来将开发一些钙钛矿电池制造设备 不会直接生产钙钛矿电池产品_焦点快看
    金辰股份(603396)近日在业绩说明会上表示,公司在钙钛... 更多>
    漫步者今日跌停 深股通净买入1.53亿元
    漫步者(002351)今日跌停,成交额15 60亿元,盘后龙虎... 更多>
    焦点报道:此贴写给做ST的朋友,告诉你们今年为什么ST这么难做
    本股神也是ST的顶尖选手,附上三张经典战役,以此证明... 更多>
    金徽股份:放弃对甘肃省陇南市西和县大桥镇鱼洞村大桥金矿采矿权的竞拍
    金徽股份(603132)5月24日晚间公告,公司结合竞拍显示... 更多>
    上海市证券同业公会:3月证券业共收17张罚单 涉及9家券商及12名从业人员-天天观速讯
    上海市证券同业公会5月24日公布,经公开市场统计,202... 更多>
    宏观不择时的全天候策略是如何运转的?看完这个十问十答就全懂了!|全球热议
    昨天,半夏因为产品单周回撤比较大冲上了热搜。李蓓本... 更多>

    苏宁易购7家苏宁易家旗舰店即将落地

    中国连锁经营协会副会长武瑞玲:零

    西黄丸|“中药抗癌第一药” 全球

    长江商学院:投资者对A股预期明显提

    中国稀土行业协会:今日稀土价格指

    当前简讯:起底强奸未成年人罪犯倪笃

    环球视点!理财日记第1144天(5.24

    产业外迁东南亚,未必是坏事

    环球热头条丨标志408锁车喇叭声(40

    淄博汇金大厦地址 淄博汇金大厦|热讯