Spring6.x對調(diào)度和異步執(zhí)行的注解支持示例詳解
1 啟用Scheduling注解
Spring為任務(wù)調(diào)度和異步方法執(zhí)行提供注解支持。
要啟用 @Scheduled
和 @Async
,在 @Configuration
類(或者在啟動類)添加 @EnableScheduling
和 @EnableAsync
,如下:
@Configuration @EnableAsync @EnableScheduling public class AppConfig { }
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, }) @EnableScheduling public class RoadSyncApplication { public static void main(String[] args) { SpringApplication.run(RoadSyncApplication.class, args); } }
你可以為你的應(yīng)用程序選擇相關(guān)的注解。例如,如果你只需要支持 @Scheduled
,可以省略 @EnableAsync
。對于更細粒度的控制,你還可以分別實現(xiàn) SchedulingConfigurer
接口和 AsyncConfigurer
接口。有關(guān)完整詳細信息,請參閱 SchedulingConfigurer 和 AsyncConfigurer javadoc。
默認處理 @Async
注解的建議模式是 proxy
,它僅允許通過代理攔截調(diào)用。使用這種方式無法攔截同一類中的本地調(diào)用。 對于更高級的攔截模式,請考慮切換到 aspectj
模式與編譯時織入或加載時織入結(jié)合使用。
2 @Scheduled 注解
可將 @Scheduled
注解以及觸發(fā)元數(shù)據(jù)添加到方法中。
2.1 fixedDelay
如下方法每5000ms執(zhí)行一次,采用固定延遲,即周期從每次先前調(diào)用的【完成時間】開始測量。
@Scheduled(fixedDelay = 5000) public void doSomething() { // 定期運行的內(nèi)容 }
默認,固定延遲、固定速率和初始延遲的值將使用ms作時間單位。如想用不同時間單位,如s或min,可在 @Scheduled
配置 timeUnit
屬性:
@Scheduled(fixedDelay = 5, timeUnit = TimeUnit.SECONDS) public void doSomething() { }
2.2 fixedRate
如需固定速率執(zhí)行,使用 fixedRate
屬性。下面的方法每五秒(從每次【調(diào)用的開始時間】間隔測量)執(zhí)行一次:
@Scheduled(fixedRate = 5, timeUnit = TimeUnit.SECONDS) public void doSomething() { }
固定延遲、固定速率的任務(wù),可通過指示等待的時間量來指定初始延遲,然后再執(zhí)行方法的第一次調(diào)用:
@Scheduled(initialDelay=1000, fixedRate=5000) public void doSomething() { // 定期運行的內(nèi)容 }
2.3 一次性任務(wù)
可只指定通過指示等待執(zhí)行方法的時間量的初始延遲:
@Scheduled(initialDelay=1000) public void doSomething() { // 只運行一次 }
若簡單的定期計劃不夠表達力,可用 cron 表達式:
@Scheduled(cron="*/5 * * * * MON-FRI") public void doSomething() { // 僅在工作日運行的內(nèi)容 }
還可使用 zone
屬性指定解析 cron 表達式的時區(qū)。
要計劃的方法須有 void 返回值,且不接受任何參數(shù)。如果方法需要與應(yīng)用程序上下文中的其他對象交互,那么這些對象通常已經(jīng)通過依賴注入。
@Scheduled
是可重復(fù)注解。如在同一方法上找到幾個 scheduled 聲明,每個聲明都將獨立處理,為每個聲明觸發(fā)單獨的觸發(fā)器。因此,這樣的共定位計劃可并行重疊并立即連續(xù)執(zhí)行多次。請確保你指定的 cron 表達式等不會意外重疊。
Spring Framework 4.3 開始,支持任何范圍的 bean 上的 @Scheduled
方法。確保在運行時不初始化同一 @Scheduled
注解類的多個實例,除非你確實希望調(diào)度回調(diào)到每個這樣的實例。
確保不要在使用 @Scheduled
注解并作為常規(guī) Spring bean 注冊到容器中的 bean 類上使用 @Configurable
。否則,你將獲得雙重初始化(一次通過容器,一次通過 @Configurable
方面),其結(jié)果是每個 @Scheduled
方法被調(diào)用兩次。
FAQ
問題
生產(chǎn)用@Scheduled注解寫定時任務(wù),5min執(zhí)行一次:
@Scheduled(cron = "0 0/5 * * * ?") public void MyTimerJobSchedule() throws Exception { //省略具體業(yè)務(wù)邏輯 System.out.println("五分鐘執(zhí)行一次"); }
過幾天,領(lǐng)導(dǎo)通知說有問題,一查日志,發(fā)現(xiàn)是定時任務(wù)問題。本來應(yīng)該是5min跑一次,結(jié)果日志發(fā)現(xiàn),每天0點-3點正常,3-10點沒執(zhí)行;一直到10-11點之間才繼續(xù)跑。
原因
發(fā)現(xiàn)可能是定時任務(wù)單線程模式導(dǎo)致任務(wù)阻塞。
繼續(xù)分析日志,發(fā)現(xiàn)該定時任務(wù)的線程號是[Scheduling-1],除了執(zhí)行自身的任務(wù),還打印了其它定時任務(wù)的輸出語句。
每天3點前,[Scheduling-1]線程在執(zhí)行本人寫的5min一次的定時任務(wù),3點后,[Scheduling-1]線程會執(zhí)行另一個比較耗時的定時任務(wù),直到10點后,[Scheduling-1]線程才重新執(zhí)行5min一次的定時任務(wù)。
看來,確實是由于@Scheduled定時任務(wù)默認使用單線程模式導(dǎo)致:一旦有一個定時任務(wù)比較耗時,就會影響到其它定時任務(wù)按時執(zhí)行。
解決方法
在定時任務(wù)加@Async注解,并在啟動類增加@EnableAsync注解,使用多線程模式執(zhí)行定時任務(wù)。
參考網(wǎng)址 http://www.dbjr.com.cn/program/3058076vb.htm
參考網(wǎng)址中有第二種解決方法,但是已說明不太好用,因此只用第一種解決方法就夠了。
以上就是Spring6.x對調(diào)度和異步執(zhí)行的注解支持示例詳解的詳細內(nèi)容,更多關(guān)于Spring6.x調(diào)度異步執(zhí)行注解的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
解析ConcurrentHashMap: 紅黑樹的代理類(TreeBin)
ConcurrentHashMap是由Segment數(shù)組結(jié)構(gòu)和HashEntry數(shù)組結(jié)構(gòu)組成。Segment的結(jié)構(gòu)和HashMap類似,是一種數(shù)組和鏈表結(jié)構(gòu),今天給大家普及java面試常見問題---ConcurrentHashMap知識,一起看看吧2021-06-06Mybatis中mapper.xml實現(xiàn)熱加載介紹
大家好,本篇文章主要講的是Mybatis中mapper.xml實現(xiàn)熱加載介紹,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下2022-01-01windows 32位eclipse遠程hadoop開發(fā)環(huán)境搭建
這篇文章主要介紹了windows 32位eclipse遠程hadoop開發(fā)環(huán)境搭建的相關(guān)資料,需要的朋友可以參考下2016-07-07