@Scheduled线程池配置能保证同一个时间的不同任务能并行执行序言【玩转spring全家桶 百度云 玩转SpringBoot之定时任务@Scheduled线程池配置】对于定时任务,在SpringBoot中只需要使用@Scheduled 这个注解就能够满足需求,它的出现也给我们带了很大的方便,我们只要加上该注解,并且根据需求设置好就可以使用定时任务了 。
但是,我们需要注意的是,@Scheduled 并不一定会按时执行 。
因为使用@Scheduled 的定时任务虽然是异步执行的,但是,不同的定时任务之间并不是并行的!!!!!!!!
在其中一个定时任务没有执行完之前,其他的定时任务即使是到了执行时间,也是不会执行的,它们会进行排队 。
也就是如果你想你不同的定时任务互不影响,到时间就会执行,那么你最好将你的定时任务方法自己搞成异步方法,这样,定时任务其实就相当于调用了一个线程执行任务,一瞬间就结束了 。比如使用:@Async
当然,也可以勉强将你的定时任务当做都会定时执行 。但是,作为一个合格的程序员
那么,如何将@Scheduled实现的定时任务变成异步的呢?此时你需要对@Scheduled进行线程池配置 。
配置示例package com.java.navtool.business.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.task.TaskExecutor;import org.springframework.scheduling.annotation.Async;import org.springframework.scheduling.annotation.EnableScheduling;import org.springframework.scheduling.annotation.SchedulingConfigurer;import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import org.springframework.scheduling.config.ScheduledTaskRegistrar;import java.util.concurrent.Executor;import java.util.concurrent.Executors;import java.util.concurrent.ThreadPoolExecutor;/** * @author :mmzsblog.cn * @date :Created in 2021/7/27 17:46 * @description:spring-boot 多线程@Scheduled注解 并发定时任务的解决方案 * @modified By: * @version: */@Configuration@EnableSchedulingpublic class ScheduleConfig implements SchedulingConfigurer {@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {taskRegistrar.setScheduler(taskExecutor());}public static final String EXECUTOR_SERVICE = "scheduledExecutor";@Bean(EXECUTOR_SERVICE)public TaskExecutor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();// 设置核心线程数executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());// 设置最大线程数executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 10);// 设置队列容量executor.setQueueCapacity(Runtime.getRuntime().availableProcessors() * 10);// 设置线程活跃时间(秒)executor.setKeepAliveSeconds(10);// 设置默认线程名称executor.setThreadNamePrefix("scheduled-");// 设置拒绝策略executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());// 等待所有任务结束后再关闭线程池executor.setWaitForTasksToCompleteOnShutdown(true);return executor;}}附带介绍一下线程池的几个参数 。需要彻底搞懂,不要死记硬背哦!
线程池参数
- 1、corePoolSize(必填):核心线程数 。
- 2、maximumPoolSize(必填):最大线程数 。
- 3、keepAliveTime(必填):线程空闲时长 。如果超过该时长,非核心线程就会被回收 。
- 4、unit(必填):指定keepAliveTime的时间单位 。常用的有:TimeUnit.MILLISECONDS(毫秒)、TimeUnit.SECONDS(秒)、TimeUnit.MINUTES(分) 。
- 5、workQueue(必填):任务队列 。通过线程池的execute()方法提交的Runnable对象将存储在该队列中 。
- 6、threadFactory(可选):线程工厂 。一般就用默认的 。
- 7、handler(可选):拒绝策略 。当线程数达到最大线程数时就要执行饱和策略 。
- 1、AbortPolicy(默认):放弃任务并抛出RejectedExecutionException异常 。
- 2、CallerRunsPolicy:由调用线程处理该任务 。
- 3、DiscardPolicy:放弃任务,但是不抛出异常 。可以配合这种模式进行自定义的处理方式 。
- 4、DiscardOldestPolicy:放弃队列最早的未处理任务,然后重新尝试执行任务 。

文章插图
简短的总结下线程池执行流程:
- 1、一个任务提交到线程池后,如果当前的线程数没达到核心线程数,则新建一个线程并且执行新任务,注意一点,这个新任务执行完后,该线程不会被销毁;
- 2、如果达到了,则判断任务队列满了没,如果没满,则将任务放入任务队列;
- 3、如果满了,则判断当前线程数量是否达到最大线程数,如果没达到,则创建新线程来执行任务,注意,如果线程池中线程数量大于核心线程数,每当有线程超过了空闲时间,就会被销毁,直到线程数量不大于核心线程数;
- 4、如果达到了最大线程数,并且任务队列满了,就会执行饱和策略;
原创公众号:Java学习之道
个人博客: www.mmzsblog.cn
喜欢就推荐一下,因为你的参与是我在写作道路上的最强动力 。
本文版权归作者淼淼之森和博客园共有,欢迎转载 。
但须在文章页面明显位置给出原文连接,否则保留追究法律责任的权利 。
- 春季老年人吃什么养肝?土豆、米饭换着吃
- 三八妇女节节日祝福分享 三八妇女节节日语录
- 老人谨慎!选好你的“第三只脚”
- 校方进行了深刻的反思 青岛一大学生坠亡校方整改校规
- 脸皮厚的人长寿!有这特征的老人最长寿
- 长寿秘诀:记住这10大妙招 100%增寿
- 春季老年人心血管病高发 3条保命要诀
- 眼睛花不花要看四十八 老年人怎样延缓老花眼
- 香槟然能防治老年痴呆症? 一天三杯它人到90不痴呆
- 老人手抖的原因 为什么老人手会抖
