1、加載使用 @Scheduled 注解的類及方法
Spring 首先會通過類 ScheduledAnnotationBeanPostProcessor 的 postProcessAfterInitialization 方法去初始化 bean,待初始化完 bean 後,就會攔截所有用到“@Scheduled”注解的方法,進行排程處理,具體細節請看下面代碼:
2、解析 @Scheduled 的内容,并将定時任務注冊到 ScheduledTaskRegistrar 中
解析相應的的注解參數,放入“定時任務清單”等待後續處理;之後在“定時任務清單”中統一執行相應的定時任務(定時任務先執行 corn,判斷定時任務的執行時間,計算出相應的下次執行時間,放入線程中,到了時間就執行。再執行按“頻率”(fixedRate)執行的定時任務,直到所有任務執行結束)。
3、執行定時任務
run 方法是排程 task 的核心,task 的執行實際上是 run 方法的執行。
下方圖檔顯示的是定時任務執行時的參數,請注意 pool size = 1,active threads = 1(線程池中隻會有一個生效的線程), queued tasks(所有的定時任務存在于隊列中)。
總結
從上面代碼可以看出,如果多個定時任務定義的是同一個時間,會根據程式加載标有 @Scheduled 方法的先後來執行。若某個定時任務一直無法執行完成,則無法設定下次任務執行時間,之後會導緻此任務後面的所有定時任務無法繼續執行,也就會出現所有的定時任務罷工的現象。是以應用 SpringBoot 的定時任務的方法中,一定不要出現“死循環”、“執行耗費大量時間”、“http持續等待無響應”的現象,否則會導緻定時任務直接罷工。針對資料量、查詢或者遠端調用特别多的場景,推薦把定時任務分段處理。