繁体   English   中英

当工作重叠时,spring @scheduled cron 的预期行为是什么?

[英]What is the expected behaviour of spring @scheduled cron when jobs would overlap?

我有一个每小时运行一次的工作,我正在使用 Spring 的 @scheduled cron 来安排它。

如果作业需要一个多小时,我从如何防止 Spring 中的日程重叠? 当第一个工作正在运行时,下一个工作不会开始。

但这是否意味着它会在第一份工作完成后开始,还是错过了机会?

如果我有一个需要 10 个小时的作业,那么所有错过的 cron 作业是否会排队,然后在第一个作业在 10 个小时后完成时一个一个执行,还是只运行第一个作业?

谢谢!

默认情况下,执行是阻塞和单线程的,这意味着它们不会并发运行。 如果您希望作业同时运行,您也可以将该方法注释为@Async 您可能还想查看不同的Executors

如果您在提供的示例问题中使用fixedDelay ,则下一项工作只会在当前工作结束后开始,加上延迟。 因此,如果您的工作需要 10 个小时并且您的fixedDelay5000 ,则下一个工作将在 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
    }

你会注意到每个数字都被打印出来了; 例如,不会跳过任何循环。

fixedRatecron的行为是不同的。

重叠的作业排队等待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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM