SpringBoot多线程并发执行定时任务

版权申明:本文为原创文章,转载请注明原文出处

原文链接:https://blog.it-follower.com/posts/1524202457.html

SpringBoot中所有定时任务默认在同一个线程中执行,即一个任务执行尚未结束时,如果另外一个任务触发时间到了,该任务也不会启动。本文将介绍如何让SpringBoot中的不同定时任务,启用多线程来并发执行。

示例分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@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");
}
}

理论上,如果互不干扰的话,三个任务的触发时间点为:

1
2
3
job1触发:0,3,6,9,12……
job2触发:0,7,14,21,28,35,42,49,56
job3触发:0,13,26,39,52

实际执行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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秒的时候并不是它们的触发时间)。

如何解决

上干货,并发执行多个定时任务,只需要新增一个线程池配置即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {

@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {

// 设置线程池
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setThreadNamePrefix("Schedule-Task-");
taskScheduler.setPoolSize(5);
taskScheduler.initialize();

scheduledTaskRegistrar.setTaskScheduler(taskScheduler);
}
}

下面再来看执行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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

三个任务都在各自的线程里执行,到点就触发,互不干扰。

评论