您好,登錄后才能下訂單哦!
前言
Spring Scheduler里有兩個(gè)概念:任務(wù)(Task)和運(yùn)行任務(wù)的框架(TaskExecutor/TaskScheduler)。TaskExecutor顧名思義,是任務(wù)的執(zhí)行器,允許我們異步執(zhí)行多個(gè)任務(wù)。TaskScheduler是任務(wù)調(diào)度器,來運(yùn)行未來的定時(shí)任務(wù)。觸發(fā)器Trigger可以決定定時(shí)任務(wù)是否該運(yùn)行了,最常用的觸發(fā)器是CronTrigger。Spring內(nèi)置了多種類型的TaskExecutor和TaskScheduler,方便用戶根據(jù)不同業(yè)務(wù)場景選擇。
本文主要介紹了關(guān)于Spring @Scheduler使用cron表達(dá)式執(zhí)行問題的相關(guān)內(nèi)容,分享出來供大家參考學(xué)習(xí),下面話不多說了,來一起看看詳細(xì)的介紹吧
主要想弄清使用Spring @Scheduler cron表達(dá)式時(shí)的兩個(gè)問題:
結(jié)論寫在前面:
下面是實(shí)驗(yàn)過程。。。。。
使用Spring @Scheduler 時(shí),默認(rèn)只有一個(gè)線程,針對上面的問題,設(shè)計(jì)了3個(gè)實(shí)驗(yàn):
實(shí)驗(yàn)一
設(shè)置Scheduler為多線程,設(shè)置一個(gè)線程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表達(dá)式,設(shè)置為多線程時(shí),同一任務(wù)前一次沒有執(zhí)行完成,不會執(zhí)行下一次
實(shí)驗(yàn)二
使用Scheduler默認(rèn)的單線程,設(shè)置兩個(gè)線程都是5秒執(zhí)行一次,一個(gè) sleep8秒,一個(gè)不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í)行時(shí)間:
執(zhí)行次數(shù) | task | 期望執(zhí)行時(shí)間 | 實(shí)際執(zhí)行時(shí)間 |
---|---|---|---|
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表達(dá)式 ,配置為一個(gè)線程時(shí),不同定時(shí)任務(wù)是串行執(zhí)行,且上次沒有執(zhí)行完時(shí)不會執(zhí)行下次
實(shí)驗(yàn)三
設(shè)置Scheduler為多線程,設(shè)置兩個(gè)線程都是5秒執(zhí)行一次,一個(gè) sleep8秒,一個(gè)不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í)行時(shí)間:
執(zhí)行次數(shù) | task | 期望執(zhí)行時(shí)間 | 實(shí)際執(zhí)行時(shí)間 |
---|---|---|---|
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表達(dá)式 ,配置為多線程時(shí),不同定時(shí)任務(wù)不是串行執(zhí)行,且上次沒有執(zhí)行完時(shí)不會執(zhí)行下次
設(shè)置定時(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í)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對億速云的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。