SpringBoot项目使用内置的单机任务调度功能详解
作者:ThinkPet
SpringBoot项目使用内置的单机任务调度功能
SpringBoot框架中提供了2个注解来让开发者快速配置来实现单机定时任务调度的功能。
分别是@EnableScheduling和 @Scheduled
配置EnableScheduling注解
@EnableScheduling注解意思是启用SpringBoot框架的单机定时任务调度的功能,这个注解要配置到app的启动类上,或者你自定义的@Configuration配置类上,一般都配置到项目的启动类上,方便查找
如下代码所示
package cn.thinkpet.springbootappscaffold; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableScheduling; @EnableScheduling //在启动类上加这个注解,表示开启springboot定时任务功能 @SpringBootApplication public class SpringbootAppScaffoldApplication { public static void main(String[] args) { SpringApplication.run(SpringbootAppScaffoldApplication.class, args); } }
定义1个组件bean,用来存放要执行调度的task任务
package cn.thinkpet.springbootappscaffold; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Slf4j @Component public class Test1Schedule { //@Scheduled注解是springboot提供的单机应用的定时任务调度解决方案 //cron是配置定时任务调度的 spring-cron表达式 // spring-cron 一共可以有6个参数 以空格分开 // 注意spring-cron 和quartz的cron不同 ,即 spring-cron不支持配置年份,没有第7个参数, // 如果需要指定年份的定时任务建议使用quartz,xxl-job,elastic-job这种分布式任务调度框架 // 秒 分 时 日 月 周 //┌───────────── second (0-59) // │ ┌───────────── minute (0 - 59) // │ │ ┌───────────── hour (0 - 23) // │ │ │ ┌───────────── day of the month (1 - 31) // │ │ │ │ ┌───────────── month (1 - 12) (or JAN-DEC) // │ │ │ │ │ ┌───────────── day of the week (0 - 7) // │ │ │ │ │ │ (0 or 7 is Sunday, or MON-SUN) // │ │ │ │ │ │ // * * * * * * // @Scheduled(cron = "0 41 21 * * ?") // 定点--21点41分0秒 执行 // @Scheduled(cron = "*/1 * * * * ?") //定频--每1秒执行1次 // 0 0 0 ? * MON#1 每月第一个星期一的零点0分0秒 // 0 0 0 ? * 5#2 每月第2个星期五的零点0分0秒 // 0 0 0 L * * 每月最后一天的零点0分0秒 // 0 0 0 * * 5L 每月最后一个星期五的零点0分0秒 //spring-cron表达式 值的常用通配符: // *:表示所有值 比如用在日 表示每一天。 // ?:表示不指定值 比如周配置 表示不指定星期几执行。 // /:表示递增触发 比如 用在分 5/20 从第五分钟开始 每增加20分钟执行一次。 // -:表示区间 比如用在 1-6 表示一月到六月执行 // # :表示每月中的第几个星期几。5#2:表示每月第2个星期五。MON#1:表示每月第1个星期一 // L :表示最后,比如每月最后一个星期天 //其他通配符可以查询官方文档 //https://docs.spring.io/spring-framework/reference/integration/scheduling.html#scheduling-cron-expression @Scheduled(cron = "0/1 * * * * ?") public void singleTaskTest1() throws InterruptedException { log.info("singleTaskTest1"); } @Scheduled(cron = "0/1 * * * * ?") public void singleTaskTest2() throws InterruptedException { log.info("singleTaskTest2"); } // @Scheduled(cron = "0/1 * * * * ?") @Scheduled(cron = "${test3.cron:0/2 * * * * ?}") //从yml或properties配置文件中读取 cron 值,读不到时使用默认的 0/2 * * * * ? public void singleTaskTest3() throws InterruptedException { log.info("singleTaskTest3"); // LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(3)); } //----------如果嫌配置cron表达式麻烦,可以使用如下的固定速度+固定延期 的方式来配置定时任务----------- // @Scheduled(initialDelay = 3000,fixedRate = 5000) //initialDelay表示第一次延迟多少毫秒执行,单位是毫秒 //fixedRate表示多久执行一次,单位是毫秒 @Scheduled(initialDelay = 3000,fixedRate = 5000) //第一次延迟3秒执行,后面间隔5秒执行一次 public void singleTaskTest4() throws InterruptedException { log.info("singleTaskTest4"); } }
application.properties文件的配置
server.port=8080 #配置singleTaskTest3的cron表达式 test3.cron=0/7 * * * * ?
重写SpringBoot任务调度使用的线程池执行器
在实际开发中,常常会有多个task并发执行的场景,此时为了实现task之间的异步,需要自定义调度器使用的 ThreadPoolTaskScheduler
package cn.thinkpet.springbootappscaffold; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.config.ScheduledTaskRegistrar; /** * 为了实现springboot 多个定时任务调度 之间的并发执行, * 需要重写 调度器使用的 ThreadPoolTaskScheduler */ @Configuration public class MyScheduledConfig implements SchedulingConfigurer { /** * 定义springboot定时任务的 --- 线程池大小 */ private static final int POOL_SIZE = 6; /** * 定义springboot定时任务的 ---自定义线程名前缀 */ private static final String TASK_THREAD_PREFIX = "my-sche-task-"; @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { //需要创建1个springboot提供的ThreadPoolTaskScheduler ThreadPoolTaskScheduler bootScheduleExecutor = new ThreadPoolTaskScheduler(); //配置这个springboot项目全部定时任务使用 的线程数是 POOL_SIZE //在实际应用中需要考虑实际任务数量,创建相应大小的线程池 bootScheduleExecutor.setPoolSize(POOL_SIZE); //配置线程名前缀 bootScheduleExecutor.setThreadNamePrefix(TASK_THREAD_PREFIX); //初始化线程池执行器 bootScheduleExecutor.initialize(); //设置 调度器使用 bootScheduleExecutor taskRegistrar.setTaskScheduler(bootScheduleExecutor); } }
测试效果
2023-06-04 18:17:03.519 INFO 16872 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2023-06-04 18:17:03.519 INFO 16872 --- [ main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService
2023-06-04 18:17:03.534 INFO 16872 --- [ main] c.t.s.SpringbootAppScaffoldApplication : Started SpringbootAppScaffoldApplication in 1.506 seconds (JVM running for 2.224)
2023-06-04 18:17:04.007 INFO 16872 --- [ my-sche-task-1] c.t.springbootappscaffold.Test1Schedule : singleTaskTest2
2023-06-04 18:17:04.007 INFO 16872 --- [ my-sche-task-2] c.t.springbootappscaffold.Test1Schedule : singleTaskTest1
2023-06-04 18:17:05.014 INFO 16872 --- [ my-sche-task-3] c.t.springbootappscaffold.Test1Schedule : singleTaskTest2
2023-06-04 18:17:05.014 INFO 16872 --- [ my-sche-task-4] c.t.springbootappscaffold.Test1Schedule : singleTaskTest1
2023-06-04 18:17:06.006 INFO 16872 --- [ my-sche-task-3] c.t.springbootappscaffold.Test1Schedule : singleTaskTest2
2023-06-04 18:17:06.006 INFO 16872 --- [ my-sche-task-6] c.t.springbootappscaffold.Test1Schedule : singleTaskTest1
2023-06-04 18:17:06.541 INFO 16872 --- [ my-sche-task-1] c.t.springbootappscaffold.Test1Schedule : singleTaskTest4
2023-06-04 18:17:07.013 INFO 16872 --- [ my-sche-task-2] c.t.springbootappscaffold.Test1Schedule : singleTaskTest1
2023-06-04 18:17:07.013 INFO 16872 --- [ my-sche-task-4] c.t.springbootappscaffold.Test1Schedule : singleTaskTest3
2023-06-04 18:17:07.013 INFO 16872 --- [ my-sche-task-5] c.t.springbootappscaffold.Test1Schedule : singleTaskTest2
2023-06-04 18:17:08.002 INFO 16872 --- [ my-sche-task-1] c.t.springbootappscaffold.Test1Schedule : singleTaskTest2
2023-06-04 18:17:08.002 INFO 16872 --- [ my-sche-task-2] c.t.springbootappscaffold.Test1Schedule : singleTaskTest1
2023-06-04 18:17:09.009 INFO 16872 --- [ my-sche-task-6] c.t.springbootappscaffold.Test1Schedule : singleTaskTest1
2023-06-04 18:17:09.009 INFO 16872 --- [ my-sche-task-1] c.t.springbootappscaffold.Test1Schedule : singleTaskTest2
2023-06-04 18:17:10.004 INFO 16872 --- [ my-sche-task-1] c.t.springbootappscaffold.Test1Schedule : singleTaskTest2
2023-06-04 18:17:10.004 INFO 16872 --- [ my-sche-task-5] c.t.springbootappscaffold.Test1Schedule : singleTaskTest1
2023-06-04 18:17:11.011 INFO 16872 --- [ my-sche-task-6] c.t.springbootappscaffold.Test1Schedule : singleTaskTest2
2023-06-04 18:17:11.011 INFO 16872 --- [ my-sche-task-5] c.t.springbootappscaffold.Test1Schedule : singleTaskTest1
2023-06-04 18:17:11.545 INFO 16872 --- [ my-sche-task-2] c.t.springbootappscaffold.Test1Schedule : singleTaskTest4
2023-06-04 18:17:12.002 INFO 16872 --- [ my-sche-task-4] c.t.springbootappscaffold.Test1Schedule : singleTaskTest1
2023-06-04 18:17:12.002 INFO 16872 --- [ my-sche-task-3] c.t.springbootappscaffold.Test1Schedule : singleTaskTest2
2023-06-04 18:17:13.009 INFO 16872 --- [ my-sche-task-1] c.t.springbootappscaffold.Test1Schedule : singleTaskTest1
2023-06-04 18:17:13.009 INFO 16872 --- [ my-sche-task-6] c.t.springbootappscaffold.Test1Schedule : singleTaskTest2
2023-06-04 18:17:14.016 INFO 16872 --- [ my-sche-task-2] c.t.springbootappscaffold.Test1Schedule : singleTaskTest1
2023-06-04 18:17:14.016 INFO 16872 --- [ my-sche-task-4] c.t.springbootappscaffold.Test1Schedule : singleTaskTest3
到此这篇关于SpringBoot项目使用内置的单机任务调度功能详解的文章就介绍到这了,更多相关SpringBoot内置的单机任务调度功能内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!