Spring @Scheduler使用cron表達式時的執(zhí)行問題詳解
前言
Spring Scheduler里有兩個概念:任務(wù)(Task)和運行任務(wù)的框架(TaskExecutor/TaskScheduler)。TaskExecutor顧名思義,是任務(wù)的執(zhí)行器,允許我們異步執(zhí)行多個任務(wù)。TaskScheduler是任務(wù)調(diào)度器,來運行未來的定時任務(wù)。觸發(fā)器Trigger可以決定定時任務(wù)是否該運行了,最常用的觸發(fā)器是CronTrigger。Spring內(nèi)置了多種類型的TaskExecutor和TaskScheduler,方便用戶根據(jù)不同業(yè)務(wù)場景選擇。
本文主要介紹了關(guān)于Spring @Scheduler使用cron表達式執(zhí)行問題的相關(guān)內(nèi)容,分享出來供大家參考學(xué)習(xí),下面話不多說了,來一起看看詳細(xì)的介紹吧
主要想弄清使用Spring @Scheduler cron表達式時的兩個問題:
- 同一定時任務(wù),第二次觸發(fā)時間到了,第一次還沒有執(zhí)行完成時會執(zhí)行嗎?
- 不同的定時任務(wù),相互之間是否有影響?
結(jié)論寫在前面:
- 同一定時任務(wù),第二次觸發(fā)時間到了,第一次還沒有執(zhí)行完成時會執(zhí)行嗎?不會,會等前一次執(zhí)行完成才執(zhí)行下一次
- 不同的定時任務(wù),相互之間是否有影響?取決于可用的定時任務(wù)線程數(shù),如果線程數(shù)足夠則不會影響;如果可用定時任務(wù)線程數(shù)少于要執(zhí)行定時任務(wù)數(shù)量,未能獲取到線程的自然要等到有空閑線程時才能執(zhí)行。
下面是實驗過程。。。。。
使用Spring @Scheduler 時,默認(rèn)只有一個線程,針對上面的問題,設(shè)計了3個實驗:
- 設(shè)置Scheduler為多線程,設(shè)置一個線程5秒執(zhí)行一次,方法體為 sleep8秒
- 使用Scheduler默認(rèn)的單線程,設(shè)置兩個線程都是5秒執(zhí)行一次,一個 sleep8秒,一個不sleep
- 設(shè)置Scheduler為多線程,設(shè)置兩個線程都是5秒執(zhí)行一次,一個 sleep8秒,一個不sleep
實驗一
設(shè)置Scheduler為多線程,設(shè)置一個線程5秒執(zhí)行一次,方法體為 sleep8秒:
@Scheduled(cron = "*/5 * * * * *")
public void test1() throws InterruptedException {
log.info("test1, 5秒執(zhí)行一次,每次執(zhí)行sleep 8s");
Thread.sleep(8000L);
}
結(jié)果:
2017-10-11 17:49:45 scheduler-1 test1, 5秒執(zhí)行一次,每次執(zhí)行sleep 8
2017-10-11 17:49:55 scheduler-1 test1, 5秒執(zhí)行一次,每次執(zhí)行sleep 8
2017-10-11 17:50:05 scheduler-1 test1, 5秒執(zhí)行一次,每次執(zhí)行sleep 8
2017-10-11 17:50:15 scheduler-2 test1, 5秒執(zhí)行一次,每次執(zhí)行sleep 8
2017-10-11 17:50:25 scheduler-2 test1, 5秒執(zhí)行一次,每次執(zhí)行sleep 8
2017-10-11 17:50:35 scheduler-1 test1, 5秒執(zhí)行一次,每次執(zhí)行sleep 8
結(jié)論:
@Scheduled使用cron表達式,設(shè)置為多線程時,同一任務(wù)前一次沒有執(zhí)行完成,不會執(zhí)行下一次
實驗二
使用Scheduler默認(rèn)的單線程,設(shè)置兩個線程都是5秒執(zhí)行一次,一個 sleep8秒,一個不sleep
如果test2每8秒執(zhí)行一次,則為串行
@Scheduled(cron = "*/5 * * * * *")
public void test1() throws InterruptedException {
System.out.println("test1, 5秒執(zhí)行一次,每次執(zhí)行sleep 8s");
Thread.sleep(8000L);
}
@Scheduled(cron = "*/5 * * * * *")
public void test2() {
System.out.println("test2, 5秒執(zhí)行一次,不sleep");
}
執(zhí)行結(jié)果:
2017-10-11 17:17:35 test2, 5秒執(zhí)行一次,不sleep
2017-10-11 17:17:35 test1, 5秒執(zhí)行一次,每次執(zhí)行sleep 8s
2017-10-11 17:17:43 test2, 5秒執(zhí)行一次,不sleep
2017-10-11 17:17:45 test1, 5秒執(zhí)行一次,每次執(zhí)行sleep 8s
2017-10-11 17:17:53 test2, 5秒執(zhí)行一次,不sleep
2017-10-11 17:17:55 test2, 5秒執(zhí)行一次,不sleep
2017-10-11 17:17:55 test1, 5秒執(zhí)行一次,每次執(zhí)行sleep 8s
2017-10-11 17:18:03 test2, 5秒執(zhí)行一次,不sleep
2017-10-11 17:18:05 test2, 5秒執(zhí)行一次,不sleep
2017-10-11 17:18:05 test1, 5秒執(zhí)行一次,每次執(zhí)行sleep 8s
2017-10-11 17:18:13 test2, 5秒執(zhí)行一次,不sleep
2017-10-11 17:18:15 test1, 5秒執(zhí)行一次,每次執(zhí)行sleep 8s
2017-10-11 17:18:23 test2, 5秒執(zhí)行一次,不sleep
2017-10-11 17:18:25 test1, 5秒執(zhí)行一次,每次執(zhí)行sleep 8s
對比期望執(zhí)行時間:
| 執(zhí)行次數(shù) | task | 期望執(zhí)行時間 | 實際執(zhí)行時間 |
|---|---|---|---|
| 1 | task1 | 17:17:35 | 17:17:35 |
| 1 | task2 | 17:17:35 | 17:17:35 |
| 2 | task1 | 17:17:40 | 17:17:43 |
| 2 | task2 | 17:17:40 | 17:17:45 |
結(jié)論:
@Scheduled使用cron表達式 ,配置為一個線程時,不同定時任務(wù)是串行執(zhí)行,且上次沒有執(zhí)行完時不會執(zhí)行下次
實驗三
設(shè)置Scheduler為多線程,設(shè)置兩個線程都是5秒執(zhí)行一次,一個 sleep8秒,一個不sleep
@Scheduled(cron = "*/5 * * * * *")
public void test1() throws InterruptedException {
log.info("test1, 5秒執(zhí)行一次,每次執(zhí)行sleep 8s");
Thread.sleep(8000L);
}
@Scheduled(cron = "*/5 * * * * *")
public void test2() {
log.info("test2, 5秒執(zhí)行一次,不sleep");
}
結(jié)果:
2017-10-11 18:12:40 scheduler-2 test2, 5秒執(zhí)行一次,不sleep
2017-10-11 18:12:40 scheduler-1 test1, 5秒執(zhí)行一次,每次執(zhí)行sleep 8s
2017-10-11 18:12:45 scheduler-2 test2, 5秒執(zhí)行一次,不sleep
2017-10-11 18:12:50 scheduler-1 test1, 5秒執(zhí)行一次,每次執(zhí)行sleep 8s
2017-10-11 18:12:50 scheduler-2 test2, 5秒執(zhí)行一次,不sleep
2017-10-11 18:12:55 scheduler-2 test2, 5秒執(zhí)行一次,不sleep
2017-10-11 18:13:00 scheduler-1 test1, 5秒執(zhí)行一次,每次執(zhí)行sleep 8s
對比期望執(zhí)行時間:
| 執(zhí)行次數(shù) | task | 期望執(zhí)行時間 | 實際執(zhí)行時間 |
|---|---|---|---|
| 1 | task1 | 18:12:40 | 18:12:40 |
| 1 | task2 | 18:12:40 | 18:12:40 |
| 2 | task1 | 18:12:45 | 18:12:50 |
| 2 | task2 | 18:12:45 | 18:12:45 |
結(jié)論:
@Scheduled使用cron表達式 ,配置為多線程時,不同定時任務(wù)不是串行執(zhí)行,且上次沒有執(zhí)行完時不會執(zhí)行下次
設(shè)置定時任務(wù)為多線程
這里用的是spring boot:
@Configuration
public class ScheduleConfig {
@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(3);
scheduler.setThreadNamePrefix("scheduler-");
return scheduler;
}
}
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
Intellij IDEA如何去掉@Autowired 注入警告的方法
這篇文章主要介紹了Intellij IDEA如何去掉@Autowired 注入警告的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
springboot+thymeleaf找不到視圖的解決方案
這篇文章主要介紹了springboot+thymeleaf找不到視圖的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06
JavaWeb開發(fā)基于ssm的校園服務(wù)系統(tǒng)(實例詳解)
這篇文章主要介紹了JavaWeb開發(fā)基于ssm的校園服務(wù)系統(tǒng),本文通過實例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2020-02-02
@Scheduled fixedDelayString 加載properties配置方式
這篇文章主要介紹了@Scheduled fixedDelayString 加載properties配置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10
Spring+Quartz配置定時任務(wù)實現(xiàn)代碼
這篇文章主要介紹了Spring+Quartz配置定時任務(wù)實現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-04-04
SpringBoot啟動時自動執(zhí)行指定方法的幾種實現(xiàn)方式
在Spring Boot應(yīng)用程序中,要實現(xiàn)在應(yīng)用啟動時自動執(zhí)行某些代碼,本文主要介紹了SpringBoot啟動時自動執(zhí)行指定方法的幾種方式,文中有相關(guān)的代碼示例供大家參考,需要的朋友可以參考下2024-03-03
SpringBoot過濾器實現(xiàn)項目內(nèi)接口過濾詳解
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何利用過濾器實現(xiàn)項目內(nèi)接口過濾,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-04-04

