java线程池合理设置最大线程数和核心线程数方式
目录
- 线程池合理设置最大线程数和核心线程数
- 一开始是这么配置的
- 后来网上查询线程池核心数配置
- 最后我是这么配置的
- 线程池核心线程数与最大线程数的区别
- 线程池策略
- 饱和策略
线程池合理设置最大线程数和核心线程数 工作中有这样一个场景,需要处理千万级别的数据的一个算法,大部分是增删查的操作。这个时候就需要使用多线程去处理。
一开始是这么配置的
@Configuration@EnableAsync(proxyTargetClass = true)//利用@EnableAsync注解开启异步任务支持@ComponentScan({"com.ctfojt.auditbcarslogo.service"}) //必须加此注解扫描包public class ThreadPoolConfig implements AsyncConfigurer {@Overridepublic 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万多。完全满足不了需求。
后来网上查询线程池核心数配置
【java线程池合理设置最大线程数和核心线程数方式】大部分都是这样的:
注:IO密集型(某大厂实践经验) 核心线程数 = CPU核数 / (1-阻塞系数)或着 CPU密集型:核心线程数 = CPU核数 + 1 IO密集型:核心线程数 = CPU核数 * 2也尝试着这么配置,结果发现效率并不理想,提高不了多少。
最后我是这么配置的
结果效率大大提升,仅用不到一天的数据,就跑完了千万级的数据。
//获取当前机器的核数public static final int cpuNum = Runtime.getRuntime().availableProcessors(); @Overridepublic 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为止。
饱和策略
当工作队列满且线程个数达到maximunPoolSize后所采取的策略
AbortPolicy
:默认策略;新任务提交时直接抛出未检查的异常RejectedExecutionException,该异常可由调用者捕获。CallerRunsPolicy
:既不抛弃任务也不抛出异常,使用调用者所在线程运行新的任务。DiscardPolicy
:丢弃新的任务,且不抛出异常。DiscardOldestPolicy
:调用poll方法丢弃工作队列队头的任务,然后尝试提交新任务自定义策略
:根据用户需要定制。
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 事件代理
- Java|Java OpenCV图像处理之SIFT角点检测详解
- java中如何实现重建二叉树
- Linux下面如何查看tomcat已经使用多少线程
- 数组常用方法一
- 【Hadoop踩雷】Mac下安装Hadoop3以及Java版本问题
- Java|Java基础——数组
- 多线程NSOperation
- RxJava|RxJava 在Android项目中的使用(一)