Java 当作业重叠时,spring@scheduled cron的预期行为是什么?
我有一个每小时运行一次的作业,我正在使用Spring的@scheduled cron来安排它 如果作业需要一个多小时,我从中了解到,在第一个作业运行时,下一个作业不会启动 但这是否意味着它将在第一项工作完成后启动,还是错过了机会 如果我有一个作业需要10小时,那么所有错过的cron作业会排队,然后在10小时后第一个作业完成时逐个执行,还是只运行第一个作业Java 当作业重叠时,spring@scheduled cron的预期行为是什么?,java,spring,cron,Java,Spring,Cron,我有一个每小时运行一次的作业,我正在使用Spring的@scheduled cron来安排它 如果作业需要一个多小时,我从中了解到,在第一个作业运行时,下一个作业不会启动 但这是否意味着它将在第一项工作完成后启动,还是错过了机会 如果我有一个作业需要10小时,那么所有错过的cron作业会排队,然后在10小时后第一个作业完成时逐个执行,还是只运行第一个作业 谢谢 默认情况下,执行是阻塞和单线程的,这意味着它们不会同时运行。如果希望作业同时运行,还可以将该方法注释为@Async。你可能还想看看不同的
谢谢 默认情况下,执行是阻塞和单线程的,这意味着它们不会同时运行。如果希望作业同时运行,还可以将该方法注释为
@Async
。你可能还想看看不同的
如果您使用的是与您提供的示例问题类似的fixedDelay
,则只有在当前作业结束并加上延迟后,下一个作业才会开始。因此,如果您的工作需要10小时,并且您的固定延迟为5000
,则下一个工作将在10小时后5秒开始
如果您使用的是fixedRate
,则下一个计划事件将排队运行,但不会跳过,如下所示:
如果此任务的任何执行时间超过其周期,则
后续执行可能会延迟开始,但不会同时执行
执行
如果只是使用cron
,那么作业将依次排队和执行(类似于fixedRate
)。您可以使用一个简单的方法来测试这一点(下面是Groovy,但也可以使用普通Java):
inti=0
@已计划(cron='***')
无效测试(){
如果(i<5)
线程。睡眠(10000)
i+=1
println'---------------------------'+i//未跳过任何值
}
你会注意到每个数字都是打印出来的;e、 g.任何周期都不会被跳过。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);
}
如图所示,重叠作业将排队,并在前一个作业完成后立即开始,没有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秒的间隔。重叠作业不排队,将被跳过。重叠作业将排队等待fixedRate,并将跳过@firstmanonmars提到的cron
如果我们希望在不等待的情况下执行相互重叠的corn调度程序,我们可以使用@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();
}
}
}
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
运行代码会得到以下输出,显示它们由多个线程以5秒的间隔并行运行:
@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();
}
}
}
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
cronjoby在单独的线程中执行。因此,当它的时间到了,一个新的线程就会产生并执行,而不管以前的执行是否是竞争的。(如果您使用fixeddelay,则它将等待以前运行的任务完成)@pvpkiran您的评论不正确。如果上一次迭代正在运行,spring计划的cron作业将不会启动,无论您有什么执行者-请参阅我链接的答案中的第二个答案。我相信Igor答案中的示例与您的断言相矛盾,即“cronjob在单独的线程中执行。因此,当它的时间到了,一个新的线程就会产生并执行,而不管以前的执行是否是竞争的。“返回的数字顺序与您的型号不符。谢谢-但您还没有回答我的问题。@Bruce更新。没有代码,这有点模棱两可,因为我以为你在问fixedDelay/fixedRate的交互w/cron.Ah好的,谢谢-你的编辑确实回答了这个问题。谢谢这不是答案,因此更适合作为评论。请查看SO指南。谢谢,我已经改进了答案,包括一个示例。