[英]What is the expected behaviour of spring @scheduled cron when jobs would overlap?
我有一个每小时运行一次的工作,我正在使用 Spring 的 @scheduled cron 来安排它。
如果作业需要一个多小时,我从如何防止 Spring 中的日程重叠? 当第一个工作正在运行时,下一个工作不会开始。
但这是否意味着它会在第一份工作完成后开始,还是错过了机会?
如果我有一个需要 10 个小时的作业,那么所有错过的 cron 作业是否会排队,然后在第一个作业在 10 个小时后完成时一个一个执行,还是只运行第一个作业?
谢谢!
默认情况下,执行是阻塞和单线程的,这意味着它们不会并发运行。 如果您希望作业同时运行,您也可以将该方法注释为@Async
。 您可能还想查看不同的Executors
。
如果您在提供的示例问题中使用fixedDelay
,则下一项工作只会在当前工作结束后开始,加上延迟。 因此,如果您的工作需要 10 个小时并且您的fixedDelay
为5000
,则下一个工作将在 10 小时后的 5 秒开始。
如果您使用的是fixedRate
那么下一个预定事件将排队等待运行,但不会被跳过,根据文档:
如果此任务的任何执行时间超过其周期,则后续执行可能会延迟开始,但不会并发执行。
如果您只是使用cron
,那么作业将依次排队和执行(类似于fixedRate
)。 你可以用一个简单的方法来测试这个(下面是在 Groovy 中,但也可以使用普通的 Java):
int i = 0
@Scheduled(cron = '* * * * * * ')
void test() {
if (i < 5)
Thread.sleep(10000)
i += 1
println '------------------------' + i // No values skipped
}
你会注意到每个数字都被打印出来了; 例如,不会跳过任何循环。
fixedRate
和cron
的行为是不同的。
重叠的作业排队等待fixedRate
(根据@Igor 的上述答案)。
cron
会跳过重叠的作业。
演示差异的示例 Java 代码:
int i = 0;
@Scheduled(fixedRate = 5000)
public void test() throws InterruptedException {
Date start = new Date();
if (i < 3) Thread.sleep(10000);
i++;
System.out.printf("start %TT, finish %TT, i = %s%n", start, new Date(), i);
}
和输出:
start 13:25:30, finish 13:25:40, i = 1
start 13:25:40, finish 13:25:50, i = 2
start 13:25:50, finish 13:26:00, i = 3
start 13:26:00, finish 13:26:00, i = 4
start 13:26:00, finish 13:26:00, i = 5
start 13:26:00, finish 13:26:00, i = 6
start 13:26:00, finish 13:26:00, i = 7
start 13:26:05, finish 13:26:05, i = 8
start 13:26:10, finish 13:26:10, i = 9
start 13:26:15, finish 13:26:15, i = 10
可以看出,重叠的作业排队并在前一个完成后立即开始,没有 5 秒的间隔。
但是,如果我们使用@Scheduled(cron = "*/5 * * ? * *")
代替,输出变为:
start 13:22:10, finish 13:22:20, i = 1
start 13:22:25, finish 13:22:35, i = 2
start 13:22:40, finish 13:22:50, i = 3
start 13:22:55, finish 13:22:55, i = 4
start 13:23:00, finish 13:23:00, i = 5
start 13:23:05, finish 13:23:05, i = 6
start 13:23:10, finish 13:23:10, i = 7
start 13:23:15, finish 13:23:15, i = 8
start 13:23:20, finish 13:23:20, i = 9
start 13:23:25, finish 13:23:25, i = 10
作业之间总是有 5 秒的间隔。 重叠的作业不会排队并被跳过。
正如@firstmanonmars 所提到的,重叠作业排队等待fixedRate并跳过cron
如果我们想在不等待的情况下执行相互重叠的玉米调度程序,我们可以使用@Async和@EnableAsync ,如下所示。
@EnableScheduling
@SpringBootApplication
@EnableAsync
public class TaskSchedulerApplication {
public static void main(String[] args) {
SpringApplication.run(TaskSchedulerApplication.class, args);
}
@Bean
public TaskScheduler taskScheduler() {
final ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(10);
return scheduler;
}
}
调度器演示:
@Component
public class DemoScheduler {
@Async
@Scheduled(cron = "*/5 * * * * MON-FRI")
public void startJob() {
System.out.println(String.format("%s - Thread name - %s ",new Date(), Thread.currentThread().getName()));
sleep(6000);
}
private void sleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行代码给出以下输出,表明它们由多个线程以 5 秒的间隔并行运行:
Thu May 06 09:59:05 IST 2021 - Thread name - task-1
Thu May 06 09:59:10 IST 2021 - Thread name - task-2
Thu May 06 09:59:15 IST 2021 - Thread name - task-3
Thu May 06 09:59:20 IST 2021 - Thread name - task-4
Thu May 06 09:59:25 IST 2021 - Thread name - task-5
Thu May 06 09:59:30 IST 2021 - Thread name - task-6
Thu May 06 09:59:35 IST 2021 - Thread name - task-7
Thu May 06 09:59:40 IST 2021 - Thread name - task-8
Thu May 06 09:59:45 IST 2021 - Thread name - task-1
Thu May 06 09:59:50 IST 2021 - Thread name - task-2
Thu May 06 09:59:55 IST 2021 - Thread name - task-3
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.