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本地任务调度设计与实现方式
相关文章
springboot后端配置多个数据源、Mysql数据库的便捷方法
实现springboot 后端配置多个数据源、Mysql数据库,只需要新建 Mapper、实体类 相应的文件夹,将不同数据源的文件保存到对应的文件夹下,添加绑定数据库配置Config,就可以轻松完成2021-08-08
启动异常invalid constant type:15的解决方案
今天小编就为大家分享一篇关于启动异常invalid constant type:15的解决方案,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧2018-12-12
Java Process与Runtime()的使用及调用cmd命令阻塞的解决方案
这篇文章主要介绍了Java Process与Runtime()的使用及调用cmd命令阻塞的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-06-06
SpringBoot项目设置断点debug调试无效忽略web.xml问题的解决
这篇文章主要介绍了SpringBoot项目设置断点debug调试无效忽略web.xml问题的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2019-08-08
SpringBoot整合Minio的过程(支持公有及私有bucket)
Bucket 是存储Object的逻辑空间,每个Bucket之间的数据是相互隔离的,对用户而言,相当于存放文件的顶层文件夹,这篇文章主要介绍了SpringBoot整合Minio的过程(支持公有及私有bucket),需要的朋友可以参考下2025-03-03


最新评论