[英]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.