SpringBoot使用Scheduling实现定时任务的示例代码
作者:palm down
Spring Boot提供了一种方便的方式来实现定时任务,即使用Spring的@Scheduled注解,通过在方法上添加@Scheduled注解,我们可以指定方法在何时执行,本文我们就给大家介绍一下SpringBoot如何使用Scheduling实现定时任务,需要的朋友可以参考下
springboot实现定时任务
开启springboot定时任务
- springboot实现定时任务很简单,只需要在启动类上加上
@EnableScheduling
就可以
/** * @author liouwb */ @SpringBootApplication @EnableScheduling public class SchedulerApplication{ public static void main(String[] args) { SpringApplication.run(SchedulerApplication.class, args); } }
- 编写测试类
/** * @author liouwb */ @Slf4j @Component public class TestJob { /** * 定时任务-串行 * 固定一秒执行一次 * * @author liouwb */ @Scheduled(cron = "0/1 * * * * ?") public void testTask1() { log.info("测试任务-1"); } }
- 执行结果
- 下面测试,如果让每次任务执行5秒
/** * 定时任务-串行 * 固定一秒执行一次 * * @author liouwb */ @Scheduled(cron = "0/1 * * * * ?") public void testTask1() throws InterruptedException { // 让每次任务执行5秒 Thread.sleep(5 * 1000); log.info("测试任务-1"); }
- 想要的结果是1一秒执行一次
- 实际执行结果,是6秒执行一次,线程串行执行
- 未达到想要的接口
原因分析:
@EnableScheduling
注解默认使用的是ThreadPoolTaskScheduler
线程池,默认线程数是1- 下面我们看下源码
- 我们看先
@EnableScheduling
注解
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Import(SchedulingConfiguration.class) @Documented public @interface EnableScheduling { }
- 看下
SchedulingConfiguration
类
@Configuration @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public class SchedulingConfiguration { @Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() { return new ScheduledAnnotationBeanPostProcessor(); } }
- 看下
ScheduledAnnotationBeanPostProcessor
类
public ScheduledAnnotationBeanPostProcessor() { this.registrar = new ScheduledTaskRegistrar(); }
- 看下
ScheduledTaskRegistrar
类,这里使用的是TaskScheduler
线程池 - 默认的是
ThreadPoolTaskScheduler
配置线程池,让定时任务指定并发执行
- 配置线程池,实现
SchedulingConfigurer
接口,实现configureTasks
方法
/** * 线程池配置 * * @author liouwb * @time 2023-07-27 */ @Configuration public class SchedulerConfig implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.setScheduler(taskScheduler()); } @Bean public TaskScheduler taskScheduler() { ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); // 设置线程池数量 taskScheduler.setPoolSize(10); // 设置线程池前缀 taskScheduler.setThreadNamePrefix("parallelScheduler-"); return taskScheduler; } }
- 执行结果
先要线程异步执行
在启动类上添加 @EnableAsync
注解
/** * @author liouwb */ @SpringBootApplication @EnableAsync @EnableScheduling public class SchedulerApplication{ public static void main(String[] args) { SpringApplication.run(SchedulerApplication.class, args); } }
- 再方法上添加
@Async
注解便可以让方法异步执行
/** * @author liouwb */ @Slf4j @Component public class TestJob { /** * 定时任务-串行 * 固定一秒执行一次 * * @author liouwb */ @Scheduled(cron = "0/1 * * * * ?") public void testTask1() throws InterruptedException { // 让每次任务执行5秒 Thread.sleep(5 * 1000); log.info("测试任务-1"); } @Async @Scheduled(cron = "0/1 * * * * ?") public void testTask2() { log.info("测试任务-2"); } }
- 执行结果,可以看到异步线程和并未用到设置的线程池
springboot异步线程池设置
springboot
异步线程池默认使用的是 ThreadPoolTaskExecutor
ThreadPoolTaskExecutor
和 ThreadPoolTaskScheduler
都在 org.springframework.scheduling.concurrent
下
``
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AsyncConfigurationSelector.class) public @interface EnableAsync {
断点可以看到默认的异步线程池,前缀为 taskScheduler-
,默认核心线程数为 10
默认线程池名称
- 下面我们自己配置异步线程池
/** * 线程池配置 * * @author liouwb */ @Configuration public class SchedulerConfig implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.setScheduler(taskScheduler()); } @Bean public TaskScheduler taskScheduler() { ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); taskScheduler.setPoolSize(10); // 设置线程池前缀 taskScheduler.setThreadNamePrefix("parallelScheduler-"); return taskScheduler; } /** * 配置异步线程池 * * @author liouwb * @rutern org.springframework.core.task.TaskExecutor */ @Bean 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("ansyScheduled-"); // 设置拒绝策略 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 等待所有任务结束后再关闭线程池 executor.setWaitForTasksToCompleteOnShutdown(true); return executor; } }
- 执行结果,可以看到配置的线程池都生效了
指定线程池执行任务
- 可以设置多个线程池
/** * 线程池配置 * * @author liouwb * @time 2023-07-27 */ @Configuration public class SchedulerConfig implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.setScheduler(taskScheduler()); } @Bean public TaskScheduler taskScheduler() { ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); taskScheduler.setPoolSize(10); // 设置线程池前缀 taskScheduler.setThreadNamePrefix("parallelScheduler-"); return taskScheduler; } /** * 配置异步线程池 * * @author liouwb * @rutern org.springframework.core.task.TaskExecutor */ @Bean 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("ansyScheduled-"); // 设置拒绝策略 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 等待所有任务结束后再关闭线程池 executor.setWaitForTasksToCompleteOnShutdown(true); return executor; } /** * 配置异步线程池2 * * @author liouwb * @rutern org.springframework.core.task.TaskExecutor */ @Bean public TaskExecutor taskExecutor2() { 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("异步线程池2-"); // 设置拒绝策略 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 等待所有任务结束后再关闭线程池 executor.setWaitForTasksToCompleteOnShutdown(true); return executor; } }
- 在执行的时候指定线程池的名称
/** * @author liouwb */ @Slf4j @Component public class TestJob { /** * 定时任务-串行 * 固定一秒执行一次 * * @author liouwb */ @Scheduled(cron = "0/1 * * * * ?") public void testTask1() throws InterruptedException { // 让每次任务执行5秒 Thread.sleep(5 * 1000); log.info("测试任务-1"); } /** * 异步执行 * * @author liouwb */ @Async @Scheduled(cron = "0/1 * * * * ?") public void testTask2() { log.info("测试任务-2"); } /** * 异步执行 * 指定使用taskExecutor2线程池 * * @author liouwb */ @Async(value = "taskExecutor2") @Scheduled(cron = "0/1 * * * * ?") public void testTask3() { log.info("测试任务-指定线程池-3"); } }
- 执行结果
以上就是SpringBoot使用Scheduling实现定时任务的示例代码的详细内容,更多关于SpringBoot Scheduling定时任务的资料请关注脚本之家其它相关文章!
您可能感兴趣的文章:
- Spring中@EnableScheduling实现定时任务代码实例
- Spring中的@EnableScheduling定时任务注解
- SpringBoot注解@EnableScheduling定时任务详细解析
- springboot通过SchedulingConfigurer实现多定时任务注册及动态修改执行周期(示例详解)
- Spring定时任务关于@EnableScheduling的用法解析
- springboot项目使用SchedulingConfigurer实现多个定时任务的案例代码
- SpringBoot使用SchedulingConfigurer实现多个定时任务多机器部署问题(推荐)
- Spring Scheduling本地任务调度设计与实现方式