spring boot 多线程并发执行定时任务
程序员文章站
2022-05-01 16:30:18
...
Spring Boot默认情况下,所有定时任务会在一个线程中去执行,下面看测试代码,定义了三个测试Job:
@Component
@Slf4j
public class TestJob {
@Scheduled(cron = "0/3 * * * * ? ")
public void job1() {
log.info("do job1 start");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("do job1 end");
}
@Scheduled(cron = "0/7 * * * * ? ")
public void job2() {
log.info("do job2");
}
@Scheduled(cron = "0/13 * * * * ? ")
public void job3() {
log.info("do job3");
}
}
理论上,如果互不干扰的话,三个任务的触发时间点为:
job1触发:0,3,6,9,12……
job2触发:0,7,14,21,28,35,42,49,56
job3触发:0,13,26,39,52
实际执行结果:
2019-03-01 14:59:24 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job1 start
2019-03-01 14:59:34 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job1 end
2019-03-01 14:59:34 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job3
2019-03-01 14:59:34 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job2
2019-03-01 14:59:35 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job2
2019-03-01 14:59:36 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job1 start
2019-03-01 14:59:46 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job1 end
2019-03-01 14:59:46 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job3
2019-03-01 14:59:46 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job2
2019-03-01 14:59:48 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job1 start
2019-03-01 14:59:58 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job1 end
2019-03-01 14:59:58 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job2
2019-03-01 14:59:58 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job3
2019-03-01 15:00:00 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job2
2019-03-01 15:00:00 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job3
2019-03-01 15:00:00 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job1 start
2019-03-01 15:00:10 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job1 end
2019-03-01 15:00:10 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job2
2019-03-01 15:00:12 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job1 start
2019-03-01 15:00:22 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job1 end
2019-03-01 15:00:22 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job3
2019-03-01 15:00:22 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job2
2019-03-01 15:00:24 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job1 start
2019-03-01 15:00:34 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job1 end
2019-03-01 15:00:34 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job3
2019-03-01 15:00:34 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job2
2019-03-01 15:00:35 INFO 7868 --- [ scheduling-1] c.yclouds.service.demo.TestJob : do job2
会看到他们的线程名都为schedule-1,观察line1-4,job1执行过程中,job2,job3触发时间到了,也没有执行。而是等job1结束后,立马执行一次(即时34秒的时候并不是它们的触发时间)。
上干货,并发执行多个定时任务,只需要新增一个线程池配置即可:
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
int corePoolSize = 5;
String nameFormat = "Schedule-Pool-%d";
// 设置线程名
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
.setNameFormat(nameFormat).build();
// 初始化线程池
ThreadPoolExecutor threadPool = new ScheduledThreadPoolExecutor(corePoolSize,
namedThreadFactory);
scheduledTaskRegistrar.setScheduler(threadPool);
}
}
下面再来看执行结果:
2019-03-01 15:21:00 INFO 11204 --- [Schedule-Pool-2] c.yclouds.service.demo.TestJob : do job1 start
2019-03-01 15:21:00 INFO 11204 --- [Schedule-Pool-4] c.yclouds.service.demo.TestJob : do job2
2019-03-01 15:21:00 INFO 11204 --- [Schedule-Pool-3] c.yclouds.service.demo.TestJob : do job3
2019-03-01 15:21:07 INFO 11204 --- [Schedule-Pool-4] c.yclouds.service.demo.TestJob : do job2
2019-03-01 15:21:10 INFO 11204 --- [Schedule-Pool-2] c.yclouds.service.demo.TestJob : do job1 end
2019-03-01 15:21:12 INFO 11204 --- [Schedule-Pool-2] c.yclouds.service.demo.TestJob : do job1 start
2019-03-01 15:21:13 INFO 11204 --- [Schedule-Pool-0] c.yclouds.service.demo.TestJob : do job3
2019-03-01 15:21:14 INFO 11204 --- [Schedule-Pool-3] c.yclouds.service.demo.TestJob : do job2
2019-03-01 15:21:21 INFO 11204 --- [Schedule-Pool-3] c.yclouds.service.demo.TestJob : do job2
2019-03-01 15:21:22 INFO 11204 --- [Schedule-Pool-2] c.yclouds.service.demo.TestJob : do job1 end
2019-03-01 15:21:24 INFO 11204 --- [Schedule-Pool-2] c.yclouds.service.demo.TestJob : do job1 start
2019-03-01 15:21:26 INFO 11204 --- [Schedule-Pool-0] c.yclouds.service.demo.TestJob : do job3
2019-03-01 15:21:28 INFO 11204 --- [Schedule-Pool-1] c.yclouds.service.demo.TestJob : do job2
2019-03-01 15:21:34 INFO 11204 --- [Schedule-Pool-2] c.yclouds.service.demo.TestJob : do job1 end
2019-03-01 15:21:35 INFO 11204 --- [Schedule-Pool-1] c.yclouds.service.demo.TestJob : do job2
2019-03-01 15:21:36 INFO 11204 --- [Schedule-Pool-0] c.yclouds.service.demo.TestJob : do job1 start
2019-03-01 15:21:39 INFO 11204 --- [Schedule-Pool-3] c.yclouds.service.demo.TestJob : do job3
2019-03-01 15:21:42 INFO 11204 --- [Schedule-Pool-4] c.yclouds.service.demo.TestJob : do job2
2019-03-01 15:21:46 INFO 11204 --- [Schedule-Pool-0] c.yclouds.service.demo.TestJob : do job1 end
2019-03-01 15:21:48 INFO 11204 --- [Schedule-Pool-0] c.yclouds.service.demo.TestJob : do job1 start
2019-03-01 15:21:49 INFO 11204 --- [Schedule-Pool-4] c.yclouds.service.demo.TestJob : do job2
2019-03-01 15:21:52 INFO 11204 --- [Schedule-Pool-2] c.yclouds.service.demo.TestJob : do job3
2019-03-01 15:21:56 INFO 11204 --- [Schedule-Pool-1] c.yclouds.service.demo.TestJob : do job2
2019-03-01 15:21:58 INFO 11204 --- [Schedule-Pool-0] c.yclouds.service.demo.TestJob : do job1 end
2019-03-01 15:22:00 INFO 11204 --- [Schedule-Pool-0] c.yclouds.service.demo.TestJob : do job1 start
2019-03-01 15:22:00 INFO 11204 --- [Schedule-Pool-1] c.yclouds.service.demo.TestJob : do job3
2019-03-01 15:22:00 INFO 11204 --- [Schedule-Pool-3] c.yclouds.service.demo.TestJob : do job2
2019-03-01 15:22:07 INFO 11204 --- [Schedule-Pool-3] c.yclouds.service.demo.TestJob : do job2
2019-03-01 15:22:10 INFO 11204 --- [Schedule-Pool-0] c.yclouds.service.demo.TestJob : do job1 end
三个任务都在各自的线程里执行,到点就触发,互不干扰。
推荐阅读
-
spring定时任务(scheduler)的串行、并行执行实现解析
-
Spring Boot @Scheduled定时任务代码实例解析
-
spring boot使用自定义的线程池执行Async任务
-
SpringBoot系列:Spring Boot集成定时任务Quartz
-
Spring Boot+Quartz实现一个实时管理的定时任务
-
Spring Boot实现简单的定时任务
-
Spring Boot @Async 异步任务执行
-
使用spring-task定时任务动态配置修改执行时间
-
Spring Boot与Kotlin定时任务的示例(Scheduling Tasks)
-
定时任务每次都执行两次的问题,慎用new ClassPathXmlApplicationContext()