簡體   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