java线程池合理设置最大线程数和核心线程数方式

 更新时间:2021年12月28日 15:59:26   作者:李振伟  
这篇文章主要介绍了java线程池合理设置最大线程数和核心线程数方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

线程池合理设置最大线程数和核心线程数

工作中有这样一个场景,需要处理千万级别的数据的一个算法,大部分是增删查的操作。这个时候就需要使用多线程去处理。

一开始是这么配置的

@Configuration
@EnableAsync(proxyTargetClass = true)//利用@EnableAsync注解开启异步任务支持
@ComponentScan({"com.ctfojt.auditbcarslogo.service"}) //必须加此注解扫描包
public class ThreadPoolConfig implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(10);//核心线程大小
        taskExecutor.setMaxPoolSize(20);//最大线程大小
        taskExecutor.setQueueCapacity(500);//队列最大容量
        //当提交的任务个数大于QueueCapacity,就需要设置该参数,但spring提供的都不太满足业务场景,可以自定义一个,也可以注意不要超过QueueCapacity即可
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        taskExecutor.setAwaitTerminationSeconds(10);
        taskExecutor.setThreadNamePrefix("BCarLogo-Thread-");
        taskExecutor.initialize();
        return taskExecutor;
    }
}

这样配置效率很低,一天大概能处理30多万的数据。往后随着插入表的数据越来越多,处理速度也随之降低,跑个一两天之后,差不多能够处理10万多。完全满足不了需求。

后来网上查询线程池核心数配置

大部分都是这样的:

注:IO密集型(某大厂实践经验) 核心线程数 = CPU核数 / (1-阻塞系数)或着 CPU密集型:核心线程数 = CPU核数 + 1 IO密集型:核心线程数 = CPU核数 * 2

也尝试着这么配置,结果发现效率并不理想,提高不了多少。

最后我是这么配置的

结果效率大大提升,仅用不到一天的数据,就跑完了千万级的数据。

//获取当前机器的核数
public static final int cpuNum = Runtime.getRuntime().availableProcessors();
@Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(cpuNum);//核心线程大小
        taskExecutor.setMaxPoolSize(cpuNum * 2);//最大线程大小
        taskExecutor.setQueueCapacity(500);//队列最大容量
        //当提交的任务个数大于QueueCapacity,就需要设置该参数,但spring提供的都不太满足业务场景,可以自定义一个,也可以注意不要超过QueueCapacity即可
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        taskExecutor.setAwaitTerminationSeconds(60);
        taskExecutor.setThreadNamePrefix("BCarLogo-Thread-");
        taskExecutor.initialize();
        return taskExecutor;
    }

完美的解决了问题!

线程池核心线程数与最大线程数的区别

线程池策略

corePoolSize:核心线程数;maximunPoolSize:最大线程数

每当有新的任务到线程池时,

  • 第一步:先判断线程池中当前线程数量是否达到了corePoolSize,若未达到,则新建线程运行此任务,且任务结束后将该线程保留在线程池中,不做销毁处理,若当前线程数量已达到corePoolSize,则进入下一步;
  • 第二步:判断工作队列(workQueue)是否已满,未满则将新的任务提交到工作队列中,满了则进入下一步;
  • 第三步:判断线程池中的线程数量是否达到了maxumunPoolSize,如果未达到,则新建一个工作线程来执行这个任务,如果达到了则使用饱和策略来处理这个任务。注意: 在线程池中的线程数量超过corePoolSize时,每当有线程的空闲时间超过了keepAliveTime,这个线程就会被终止。直到线程池中线程的数量不大于corePoolSize为止。

(由第三步可知,在一般情况下,Java线程池中会长期保持corePoolSize个线程。)

饱和策略

当工作队列满且线程个数达到maximunPoolSize后所采取的策略

  • AbortPolicy:默认策略;新任务提交时直接抛出未检查的异常RejectedExecutionException,该异常可由调用者捕获。
  • CallerRunsPolicy:既不抛弃任务也不抛出异常,使用调用者所在线程运行新的任务。
  • DiscardPolicy:丢弃新的任务,且不抛出异常。
  • DiscardOldestPolicy:调用poll方法丢弃工作队列队头的任务,然后尝试提交新任务
  • 自定义策略:根据用户需要定制。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 解决rocketmq-spring-boot-starter导致的多消费者实例重复消费问题

    解决rocketmq-spring-boot-starter导致的多消费者实例重复消费问题

    这篇文章主要介绍了解决rocketmq-spring-boot-starter导致的多消费者实例重复消费问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • springboot使用webservice发布和调用接口的实例详解

    springboot使用webservice发布和调用接口的实例详解

    本文介绍了如何在Springboot中使用webservice发布和调用接口,涵盖了必要的依赖添加和代码示例,文中提供了服务端和客户端的实现方法,以及如何设置端口和服务地址,帮助读者更好地理解和应用Springboot结合webservice的技术
    2024-10-10
  • 学生视角带你了解Java内部类

    学生视角带你了解Java内部类

    说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉。原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法。今天我们就来一探究竟
    2022-03-03
  • 简单了解Spring中的事务控制

    简单了解Spring中的事务控制

    这篇文章主要介绍了简单了解Spring中的事务控制,事务是一组操作的执行单元,下面我们来简单学习一下吧
    2019-05-05
  • Java异步编程之Callbacks与Futures模型详解

    Java异步编程之Callbacks与Futures模型详解

    这篇文章主要为大家详细介绍了Java异步编程中Callbacks与Futures模型的使用,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-03-03
  • 深入探究一下Java中不同的线程间数据通信方式

    深入探究一下Java中不同的线程间数据通信方式

    这篇文章主要来和大家一起深入探究一下Java中不同的线程间数据通信方式,文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以参考一下
    2023-04-04
  • 解决Spring security5.5.7报错Encoded password does not look like BCrypt异常

    解决Spring security5.5.7报错Encoded password does

    这篇文章主要介绍了解决Spring security5.5.7出现Encoded password does not look like BCrypt异常问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • 详解SpringBoot如何自定义一个Starter

    详解SpringBoot如何自定义一个Starter

    小伙伴们曾经可能都经历过整天写着CURD的业务,都没写过一些组件相关的东西,这篇文章记录一下SpringBoot如何自定义一个Starter。原理和理论就不用多说了,可以在网上找到很多关于该方面的资料,这里主要分享如何自定义
    2022-11-11
  • java 使用idea将工程打成jar并创建成exe文件类型执行的方法详解

    java 使用idea将工程打成jar并创建成exe文件类型执行的方法详解

    这篇文章主要介绍了java 使用idea将工程打成jar并创建成exe文件类型执行,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2020-09-09
  • SpringBoot将项目打成war包步骤解析

    SpringBoot将项目打成war包步骤解析

    这篇文章主要介绍了SpringBoot将项目打成war包步骤解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03

最新评论