SpringBoot+@EnableScheduling使用定時(shí)器的常見(jiàn)案例
記錄一下SpringBoot+@EnableScheduling使用定時(shí)器的常見(jiàn)案例
我的SpringBoot版本
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>
啟動(dòng)類
package boot.example.timer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableScheduling public class App { public static void main( String[] args ) { SpringApplication.run(App.class, args); System.out.println( "Hello World!" ); } }
必須加上這個(gè)注解 @EnableScheduling
定時(shí)器TimerService
package boot.example.timer.timer; import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @Service public class TimerService { @Scheduled(cron = "0/1 * * * * ?") public void timerTest() throws IOException { long now = System.currentTimeMillis(); DateFormat format = new SimpleDateFormat("yyyy-MM-dd:HH:mm:ss"); System.out.println("timer--"+format.format(now)); } }
有很多的cron表達(dá)式來(lái)指定任務(wù)在需要的時(shí)間執(zhí)行,可是有時(shí)候讓人頭疼,明明設(shè)置的cron是對(duì)的,可就是到點(diǎn)不執(zhí)行,回過(guò)頭來(lái)發(fā)現(xiàn)cron就是寫錯(cuò)了,這很尷尬。
cron表達(dá)式 秒鐘(1) 分鐘(2) 小時(shí)(3) 日期(4) 月份(5) 星期(6) 年(7) 長(zhǎng)度是7 可為啥我們?cè)诔绦蚶飳懙拈L(zhǎng)度只有6呢?
比如我每秒鐘執(zhí)行一次
@Scheduled(cron = "0/1 * * * * * ?") // SpringBoot運(yùn)行報(bào)錯(cuò)
@Scheduled(cron = "0/1 * * * * ?") // SpringBoot運(yùn)行正常
那是因?yàn)槟?7) 稍微特殊,他可以是空或者1970-2099 允許的字符有 , - * / 四種符號(hào),實(shí)際沒(méi)有(問(wèn)號(hào)) ,可能是按照規(guī)律去推以為有問(wèn)號(hào)而已。
那么這個(gè)?問(wèn)號(hào)到底是啥意思??問(wèn)號(hào)字符只在日期(4)和星期(6)中使用,表示不確定的值 當(dāng)需要的時(shí)候在使用,日期(4)和星期(6)是互相拉扯的,用?問(wèn)號(hào)可以表示不想設(shè)置。
秒(1)的案例
1分鐘有60秒 因此允許值范圍是0-59符號(hào)*表示每秒符號(hào),表示指定的秒數(shù)觸發(fā) 比如 0,2,4,6 那么就在單位分鐘內(nèi)的 0 2 4 6那個(gè)點(diǎn)觸發(fā)執(zhí)行符號(hào)-表示指定范圍區(qū)間 比如 20-40 那么就是在20到40s的區(qū)間內(nèi)每秒執(zhí)行符號(hào)/表示步進(jìn) 比如 0/1 從0秒開(kāi)始每秒觸發(fā) 0/10 從0秒開(kāi)始每隔10s觸發(fā)一次
1.1s執(zhí)行一次
@Scheduled(cron = "* * * * * ?")
@Scheduled(cron = "0/1 * * * * ?")
2.指定在 2s 17s 34s 52s 這四個(gè)秒鐘點(diǎn)執(zhí)行
@Scheduled(cron = "2,17,34,52 * * * * ?")
3.指定在20 - 30s內(nèi)每秒執(zhí)行
@Scheduled(cron = "20-30 * * * * ?")
測(cè)試可以看到是閉區(qū)間的
4.從0秒開(kāi)始每隔10s觸發(fā)一次
@Scheduled(cron = "0/10 * * * * ?")
5.從5秒開(kāi)始每隔40s觸發(fā)一次 注意這里!?。?!
@Scheduled(cron = "5/40 * * * * ?")
從運(yùn)行的打印日志可以看到確實(shí)是從5s開(kāi)始 40s后到了45秒執(zhí)行了一次 可下一個(gè)40s就不是這么算的了 也就是說(shuō)并不是每次間隔40s了,這里是20s 40s 如此的 相當(dāng)于在5s執(zhí)行了一次 45s執(zhí)行了一次,原因嘛,反正就那樣執(zhí)行的。
6.在5-40s閉區(qū)間內(nèi)每隔2s執(zhí)行一次,這種是兩種符號(hào)的一起用
@Scheduled(cron = "5-40/2 * * * * ?")
其他符號(hào)的組合?不嘗試了,有空再說(shuō)。
分鐘(2)的案例
1小時(shí)有60分鐘 因此允許值范圍是0-59 和 秒一樣的范圍符號(hào)*表示每分鐘符號(hào),表示指定的分鐘觸發(fā) 比如 0,2,4,6 那么就在單位小時(shí)內(nèi)的指定分鐘數(shù) 0 2 4 6分那個(gè)點(diǎn)觸發(fā)執(zhí)行符號(hào)-表示指定范圍區(qū)間 比如 20-40 那么就是在20到40分鐘的點(diǎn)位區(qū)間內(nèi)每分鐘執(zhí)行符號(hào)/表示步進(jìn) 比如 0/1 從0分鐘開(kāi)始每分鐘觸發(fā), 0/10 從0分鐘開(kāi)始每隔10分鐘觸發(fā)一次
可以發(fā)現(xiàn)這些符號(hào)的意思很通用
1.1分鐘執(zhí)行一次,此時(shí)秒的那一項(xiàng)設(shè)置為0
@Scheduled(cron = "0 * * * * ?")
@Scheduled(cron = "0 0/1 * * * ?")
2.指定在 26 28 32 34 這四個(gè)分鐘點(diǎn)執(zhí)行
@Scheduled(cron = "0 26,28,32,34 * * * ?")
3.指定在38 - 45閉區(qū)間這段分鐘時(shí)間內(nèi)每分鐘執(zhí)行
@Scheduled(cron = "0 38-45 * * * ?")
4.從0分鐘開(kāi)始每隔2分鐘觸發(fā)一次
@Scheduled(cron = "0 0/2 * * * ?")
5.從5分鐘開(kāi)始每隔40分鐘觸發(fā)一次(實(shí)際并不完全是40分鐘)
@Scheduled(cron = "0 5/40 * * * ?")
這里和分鐘同樣的問(wèn)題 執(zhí)行實(shí)際上是 每小時(shí)5分那個(gè)點(diǎn)和45分那個(gè)點(diǎn)執(zhí)行 那就是說(shuō)1個(gè)小時(shí)內(nèi)執(zhí)行兩次 5分到45分 間隔40分鐘,45分到下一個(gè)5分間隔20分鐘,這里得注意并不是每隔40分鐘。
6.在20-40分鐘閉區(qū)間內(nèi)每隔3分鐘執(zhí)行一次,這種是兩種符號(hào)的一起用
@Scheduled(cron = "0 20-40/3 * * * ?")
其他的分鐘相關(guān)的不嘗試了。
小時(shí)(3)的案例
一天有24小時(shí) 因此允許值范圍是0-23符號(hào)*表示每小時(shí)符號(hào),表示指定的小時(shí)鐘點(diǎn)觸發(fā) 比如 1,6, 12, 19那么就在一天的 1 6 12 19點(diǎn)鐘觸發(fā)執(zhí)行符號(hào)-表示指定范圍區(qū)間 比如 8-20 那么就是在早8點(diǎn)到晚上8點(diǎn)每隔1個(gè)小時(shí)執(zhí)行一次符號(hào)/表示步進(jìn) 比如 0/1 從0時(shí)開(kāi)始每小時(shí)觸發(fā) 0/2 從0點(diǎn)鐘開(kāi)始每隔2小時(shí)觸發(fā)一次,2/3 從2點(diǎn)鐘開(kāi)始每隔3小時(shí)執(zhí)行一次
1.每小時(shí)執(zhí)行一次
@Scheduled(cron = "0 0 * * * ?")
@Scheduled(cron = "0 0 0/1 * * ?")
2.在15點(diǎn)到17點(diǎn)之間每隔一小時(shí)執(zhí)行一次
@Scheduled(cron = "0 0 15-17 * * ?")
3.指定在 2點(diǎn)鐘 10點(diǎn)鐘 12點(diǎn)鐘 18點(diǎn)鐘 這四個(gè)小時(shí)點(diǎn)位執(zhí)行
@Scheduled(cron = "0 0 2,10,12,18 * * ?")
4.從0時(shí)開(kāi)始每隔4小時(shí)觸發(fā)一次
@Scheduled(cron = "0 0 0/4 * * ?")
5.從2點(diǎn)鐘開(kāi)始每隔18小時(shí)觸發(fā)一次 注意?。。。?/strong>
@Scheduled(cron = "0 0 2/18 * * ?")
這里沒(méi)去測(cè)試了,等的時(shí)間太久了,2點(diǎn)鐘執(zhí)行一次 18小時(shí)候20點(diǎn)鐘執(zhí)行一下,下一個(gè)就超過(guò)了24小時(shí),因此在第二天的2點(diǎn)鐘執(zhí)行一次,這樣間隔是6小時(shí) 18小時(shí),并不一定是每次間隔18小時(shí)的,得注意小時(shí)的范圍是0-23。
6.在2-18點(diǎn)鐘閉區(qū)間內(nèi)每隔3小時(shí)執(zhí)行一次,這種是兩種符號(hào)的一起用
@Scheduled(cron = "0 0 2-18/3 * * ?")
日期(4)的案例
一個(gè)月大概是30天 有31天的 因此允許值范圍是1-31 如果說(shuō)當(dāng)月沒(méi)有第31天 那么會(huì)拋出異常符號(hào)*表示每天符號(hào),表示指定的天觸發(fā) 比如 1,3, 5, 7那么就在當(dāng)月的 第一天,第三天,第五天,第七天觸發(fā)執(zhí)行符號(hào)-表示指定范圍區(qū)間 比如 2-20 那么就是在當(dāng)月的第二天到第二十天之間每隔一天執(zhí)行一次,閉區(qū)間內(nèi),第二天和第二十天也包含在內(nèi)符號(hào)/表示步進(jìn) 比如 2/3表示從第2天開(kāi)始每隔3天執(zhí)行一次,1/1表示從第一天開(kāi)始每天執(zhí)行一次符號(hào)?表示不確定的值,很少用到的符號(hào)L在這里表示當(dāng)月的最后一天符號(hào)W表示指定離給定日期最近的工作日(周一到周五) 沒(méi)用過(guò)符號(hào)C意思是Calendar,沒(méi)用過(guò)
這里寫幾個(gè)案例(未測(cè)試驗(yàn)證)
1.每天執(zhí)行一次
@Scheduled(cron = "0 0 0 1/1 * ?")
@Scheduled(cron = "0 0 0 * * ?")
2.當(dāng)月的1,3,5,7四天執(zhí)行一次
@Scheduled(cron = "0 0 0 1,3,5,7 * ?")
3.2-20日每天執(zhí)行一次
@Scheduled(cron = "0 0 0 2-20 * ?")
4.10-25日每隔三天執(zhí)行
@Scheduled(cron = "0 0 0 10-25/3 * ?")
月份(5)的案例
一年有12個(gè)月 因此允許值范圍是1-12,或者英文JAN-DEC符號(hào)*表示每個(gè)月符號(hào),表示指定的月份觸發(fā) 比如 1,6, 12那么就在1月 6月 12月觸發(fā)執(zhí)行符號(hào)-表示指定范圍區(qū)間 比如 2-8 那么就是在2月到8月的閉區(qū)間內(nèi)每月執(zhí)行一次符號(hào)/表示步進(jìn) 比如 1/1 從1月開(kāi)始每隔一個(gè)月觸發(fā)一次,2/3 從2月開(kāi)始每隔3個(gè)月執(zhí)行一次
英文12個(gè)月份的縮寫
1月-1-JAN2月-2-FEB3月-3-MAR4月-4-APR5月-5-MAY6月-6-JUN7月-7-JUL8月-8-AUG9月-9-SEP10月-10-OCT11月-11-NOV12月-12-DEC
這里寫幾個(gè)案例(未測(cè)試驗(yàn)證)
1.每月執(zhí)行一次
@Scheduled(cron = "0 0 0 1 * ?")
@Scheduled(cron = "0 0 0 1 1/1 ?")
2.2月,4月,6月,8月執(zhí)行一次
@Scheduled(cron = "0 0 0 1 2,4,6,8 ?")
@Scheduled(cron = "0 0 0 1 FEB,APR,JUN,AUG ?")
3.2月-10月每隔三個(gè)月執(zhí)行一次
@Scheduled(cron = "0 0 0 1 2-10/3 ?")
@Scheduled(cron = "0 0 0 1 FEB-OCT/3 ?")
其他的遇到再記錄
星期(6)的案例
一個(gè)星期有七天 因此允許值范圍是1-7 當(dāng)然也可以英文字母(SUN-SAT)符號(hào)*表示每個(gè)星期符號(hào),表示指定的星期幾觸發(fā)符號(hào)-表示指定范圍區(qū)間符號(hào)/表示步進(jìn)符號(hào)L 當(dāng)用在星期里的話表示星期的最后一天也就是星期六觸發(fā),在L前面加數(shù)字 比如2L 3L這種表示每個(gè)月的最后一個(gè)星期的星期幾執(zhí)行一次,有些難以理解,很多博客資料都這樣說(shuō)就這樣定吧,測(cè)試的話花的時(shí)間太長(zhǎng),免了不去驗(yàn)證了!
其他符號(hào)略過(guò)
這里著重注意?。。。。?/strong>星期的話 用英文字母 :星期天-SUN, 星期一-MON, 星期二-TUE, 星期三-WED, 星期四-THU,星期五-FRI,星期六-STA星期的話 用數(shù)字 是從星期一開(kāi)始的,并不是星期天,這倒是有個(gè)坑在這里兒,也就是說(shuō) 星期天-7,星期一-1,星期二-2,星期三-3,星期四-4,星期五-5,星期六-6
我這里使用的是SpringBoot2.0.x做的測(cè)試
可以證明至少在這個(gè)版本1-7指的是星期一到星期天
可以查日歷知道2023-07-19就是星期三 我寫了一個(gè)執(zhí)行的cron 星期三對(duì)應(yīng)的就是3
就是說(shuō)1對(duì)應(yīng)的不是星期天 而是星期一
再看直接寫WED 星期三
所以建議使用字母方式
這里寫幾個(gè)案例(未測(cè)試驗(yàn)證)
1.每周星期三的零點(diǎn)零分零秒執(zhí)行一次
@Scheduled(cron = "0 0 0 ? * WED")
@Scheduled(cron = "0 0 0 ? * 3")
2.星期天,星期二,星期四零點(diǎn)零分零秒執(zhí)行一次
@Scheduled(cron = "0 0 0 ? * SUN,TUE,THU")
@Scheduled(cron = "0 0 0 ? * 7,2,4")
3.工作日每天零點(diǎn)零分零秒執(zhí)行一次(星期一到星期五)
@Scheduled(cron = "0 0 0 ? * MON-FRI")
@Scheduled(cron = "0 0 0 ? * 1-5")
4.星期一到星期天 每隔兩天執(zhí)行一次
@Scheduled(cron = "0 0 0 ? * MON-STA/2")
@Scheduled(cron = "0 0 0 ? * 1-6/2")
其他單獨(dú)關(guān)于星期的案例用到再補(bǔ)充
年(7)的案例
這個(gè)世界有多少年,都不知道,目前年份很少用到,要么留空,要么區(qū)間1970-2099年閉區(qū)間內(nèi)符號(hào)*表示每年符號(hào),表示指定的年觸發(fā) 比如 2023,2025, 2030那么就在那年會(huì)觸發(fā)執(zhí)行符號(hào)-表示指定范圍區(qū)間 比如 2023-2033 那么就是在2023年到2033年每年執(zhí)行一次符號(hào)/表示步進(jìn) 比如 2023/1 從2023年開(kāi)始每年觸發(fā)一次 2023/3 從2023年開(kāi)始每隔3年執(zhí)行一次
按年的例子,沒(méi)有用到過(guò),隨意嘗試了幾個(gè),程序都報(bào)錯(cuò),也不是剛需,于是不去折騰例子了,先按照符號(hào)表達(dá)的意思去理解,如果有問(wèn)題在更改。
到此這篇關(guān)于SpringBoot+@EnableScheduling使用定時(shí)器的常見(jiàn)案例的文章就介紹到這了,更多相關(guān)SpringBoot+@EnableScheduling定時(shí)器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java設(shè)計(jì)模式之觀察者模式_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章給大家介紹流量java設(shè)計(jì)模式之觀察者模式,定義對(duì)象間一種一對(duì)多的依賴關(guān)系,使得當(dāng)每一個(gè)對(duì)象改變狀態(tài)。下面通過(guò)類圖和實(shí)例代碼給大家介紹java設(shè)計(jì)模式之觀察者模式,感興趣的朋友一起看看吧2017-08-08Java基礎(chǔ) Servlet監(jiān)聽(tīng)器詳解
這篇文章主要介紹了Java基礎(chǔ) Servlet監(jiān)聽(tīng)器詳解的相關(guān)資料,需要的朋友可以參考下2017-07-07SpringBoot中使用JeecgBoot的Autopoi導(dǎo)出Excel的方法步驟
這篇文章主要介紹了SpringBoot中使用JeecgBoot的Autopoi導(dǎo)出Excel的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09Java多線程教程之如何利用Future實(shí)現(xiàn)攜帶結(jié)果的任務(wù)
Callable與Future兩功能是Java?5版本中加入的,這篇文章主要給大家介紹了關(guān)于Java多線程教程之如何利用Future實(shí)現(xiàn)攜帶結(jié)果任務(wù)的相關(guān)資料,需要的朋友可以參考下2021-12-12Java中方法優(yōu)先調(diào)用可選參數(shù)還是固定參數(shù)
這篇文章主要介紹了Java中方法優(yōu)先調(diào)用可選參數(shù)還是固定參數(shù),可選參數(shù)是?JDK?5?中新增的特性,也叫變長(zhǎng)參數(shù)或可變參數(shù),固定參數(shù)的概念恰好與可選參數(shù)相反,固定參數(shù)也就是普通的參,下文更多詳細(xì)內(nèi)容需要的小伙伴可以參考一下2022-05-05Java微服務(wù)分布式調(diào)度Elastic-job環(huán)境搭建及配置
Elastic-Job在配置中提供了JobEventConfiguration,支持?jǐn)?shù)據(jù)庫(kù)方式配置,會(huì)在數(shù)據(jù)庫(kù)中自動(dòng)創(chuàng)建JOB_EXECUTION_LOG和JOB_STATUS_TRACE_LOG兩張表以及若干索引,來(lái)記錄作業(yè)的相關(guān)信息2023-02-02圖解Java經(jīng)典算法冒泡排序的原理與實(shí)現(xiàn)
冒泡排序是一種簡(jiǎn)單的排序算法,它也是一種穩(wěn)定排序算法。其實(shí)現(xiàn)原理是重復(fù)掃描待排序序列,并比較每一對(duì)相鄰的元素,當(dāng)該對(duì)元素順序不正確時(shí)進(jìn)行交換。一直重復(fù)這個(gè)過(guò)程,直到?jīng)]有任何兩個(gè)相鄰元素可以交換,就表明完成了排序2022-09-09