Spring??@Scheduled中這些參數(shù)的區(qū)別、組合和應(yīng)用場(chǎng)景解析
SpringBoot Scheduled 常見用法:http://m.fzitv.net/program/33832939q.htm
1. 基本概念對(duì)比
cron
- 定義:使用 Unix/Linux 風(fēng)格的 cron 表達(dá)式
- 語法:
秒 分 時(shí) 日 月 周 年(可選) - 特點(diǎn):
- 基于日歷的調(diào)度
- 執(zhí)行時(shí)間固定
- 適合在特定時(shí)間點(diǎn)執(zhí)行任務(wù)
// 每天凌晨1點(diǎn)執(zhí)行 @Scheduled(cron = "0 0 1 * * ?") // 每5分鐘執(zhí)行(在每分鐘的0秒執(zhí)行) @Scheduled(cron = "0 */5 * * * ?") // 每小時(shí)的10分、30分、50分執(zhí)行 @Scheduled(cron = "0 10,30,50 * * * ?")
fixedRate
- 定義:固定頻率執(zhí)行,從上一次開始時(shí)間開始計(jì)算間隔
- 特點(diǎn):
- 固定頻率,不關(guān)心任務(wù)執(zhí)行時(shí)間
- 如果任務(wù)執(zhí)行時(shí)間超過間隔,會(huì)立即開始下一次執(zhí)行
- 可能造成任務(wù)重疊
// 每5分鐘執(zhí)行一次(從上次開始算起) @Scheduled(fixedRate = 5 * 60 * 1000)
fixedDelay
- 定義:固定延遲執(zhí)行,從上一次結(jié)束時(shí)間開始計(jì)算間隔
- 特點(diǎn):
- 保證任務(wù)執(zhí)行間隔
- 不會(huì)出現(xiàn)任務(wù)重疊
- 適合需要保證任務(wù)串行執(zhí)行的場(chǎng)景
// 上次執(zhí)行結(jié)束后,等待5分鐘再執(zhí)行下次 @Scheduled(fixedDelay = 5 * 60 * 1000)
initialDelay
- 定義:首次執(zhí)行延遲時(shí)間
- 特點(diǎn):
- 只在第一次執(zhí)行前等待
- 可以與 fixedRate 或 fixedDelay 組合使用
- 不影響后續(xù)執(zhí)行間隔
// 應(yīng)用啟動(dòng)后等待10分鐘,然后每5分鐘執(zhí)行一次 @Scheduled(initialDelay = 10 * 60 * 1000, fixedRate = 5 * 60 * 1000)
2. 執(zhí)行行為對(duì)比
假設(shè)任務(wù)執(zhí)行需要2分鐘:
// 情況1:fixedRate = 5分鐘 // 時(shí)間線:0分開始→2分結(jié)束→5分開始→7分結(jié)束→10分開始... // 實(shí)際間隔:3分鐘(5-2) // 情況2:fixedDelay = 5分鐘 // 時(shí)間線:0分開始→2分結(jié)束→7分開始→9分結(jié)束→14分開始... // 實(shí)際間隔:7分鐘(2+5) // 情況3:cron = "0 */5 * * * ?" // 時(shí)間線:0分開始→2分結(jié)束→5分開始→7分結(jié)束→10分開始... // 實(shí)際間隔:3分鐘,但開始時(shí)間固定在0、5、10分
3. 組合使用場(chǎng)景
組合1:initialDelay + fixedRate
@Component
public class DataSyncScheduler {
// 應(yīng)用啟動(dòng)后等待2小時(shí)(讓其他服務(wù)就緒),然后每30分鐘同步一次
@Scheduled(initialDelay = 2 * 60 * 60 * 1000,
fixedRate = 30 * 60 * 1000)
public void syncData() {
// 數(shù)據(jù)同步任務(wù),執(zhí)行時(shí)間較短
}
}適用場(chǎng)景:
- 系統(tǒng)啟動(dòng)后需要等待依賴服務(wù)就緒
- 定時(shí)數(shù)據(jù)同步
- 緩存刷新
組合2:initialDelay + fixedDelay
@Component
public class ReportGenerator {
// 應(yīng)用啟動(dòng)后等待5分鐘,然后每次執(zhí)行結(jié)束后等待1小時(shí)再執(zhí)行
@Scheduled(initialDelay = 5 * 60 * 1000,
fixedDelay = 60 * 60 * 1000)
public void generateReport() {
// 生成報(bào)表,執(zhí)行時(shí)間較長(zhǎng)(約10-20分鐘)
// 保證每次生成完成后,休息1小時(shí)再開始
}
}適用場(chǎng)景:
- 執(zhí)行時(shí)間較長(zhǎng)的任務(wù)
- 需要保證任務(wù)不重疊
- 資源密集型操作
組合3:動(dòng)態(tài)計(jì)算 initialDelay
@Component
public class MaintenanceTask {
@PostConstruct
public void init() {
// 計(jì)算到下一個(gè)整點(diǎn)的延遲
}
@Scheduled(cron = "0 0 */2 * * ?", zone = "Asia/Shanghai")
public void maintenance() {
// 每2小時(shí)在整點(diǎn)執(zhí)行系統(tǒng)維護(hù)
}
}4. 具體應(yīng)用場(chǎng)景推薦
使用 cron 的場(chǎng)景:
- 每日定時(shí)任務(wù):每天凌晨備份數(shù)據(jù)庫
- 工作日特定時(shí)間:工作日9:00發(fā)送日?qǐng)?bào)
- 復(fù)雜時(shí)間規(guī)則:每月最后一天23:30執(zhí)行
- 需要固定執(zhí)行時(shí)刻:整點(diǎn)、半點(diǎn)執(zhí)行
// 工作日早上9點(diǎn)執(zhí)行 @Scheduled(cron = "0 0 9 * * MON-FRI") // 每小時(shí)的第5分鐘執(zhí)行 @Scheduled(cron = "0 5 * * * ?") // 每月1號(hào)凌晨2點(diǎn)執(zhí)行 @Scheduled(cron = "0 0 2 1 * ?")
使用 fixedRate 的場(chǎng)景:
- 監(jiān)控類任務(wù):每30秒檢查系統(tǒng)狀態(tài)
- 實(shí)時(shí)數(shù)據(jù)拉取:每5分鐘從API獲取最新數(shù)據(jù)
- 心跳檢測(cè):每10秒發(fā)送心跳包
- 緩存刷新:定期刷新緩存,不關(guān)心執(zhí)行時(shí)長(zhǎng)
// 實(shí)時(shí)監(jiān)控,頻率優(yōu)先 @Scheduled(fixedRate = 30 * 1000) // 每30秒 // 頻繁的小任務(wù) @Scheduled(fixedRate = 5 * 1000) // 每5秒
使用 fixedDelay 的場(chǎng)景:
- 批處理任務(wù):數(shù)據(jù)處理完成后需要冷卻
- 文件處理:處理完一個(gè)文件再處理下一個(gè)
- API調(diào)用限制:避免觸發(fā)API頻率限制
- 數(shù)據(jù)庫操作:大數(shù)據(jù)量操作需要間隔
// 處理大量數(shù)據(jù),需要間隔 @Scheduled(fixedDelay = 10 * 60 * 1000) // 每次間隔10分鐘 // 調(diào)用有限制的第三方API @Scheduled(fixedDelay = 2 * 1000) // 每次間隔2秒,避免限流
使用 initialDelay 的場(chǎng)景:
- 應(yīng)用啟動(dòng)延遲:等待配置加載完成
- 服務(wù)發(fā)現(xiàn)延遲:等待注冊(cè)中心就緒
- 數(shù)據(jù)預(yù)熱:等待緩存加載
- 避開啟動(dòng)高峰:應(yīng)用啟動(dòng)后不立即執(zhí)行任務(wù)
// Spring Cloud 配置,等待配置中心就緒 @Scheduled(initialDelay = 30 * 1000, fixedRate = 60 * 1000) // 緩存預(yù)熱后再執(zhí)行 @Scheduled(initialDelay = 2 * 60 * 1000, cron = "0 */15 * * * ?")
5. 實(shí)際項(xiàng)目中的最佳實(shí)踐
場(chǎng)景:你的需求(8:37啟動(dòng),8:42執(zhí)行)
@Component
public class CustodySyncService {
@PostConstruct
public void init() {
// 可以在這里計(jì)算動(dòng)態(tài)的 initialDelay
}
// 方案1:使用 cron + 動(dòng)態(tài)初始延遲(需要自己實(shí)現(xiàn))
// 方案2:使用 fixedRate + 計(jì)算的 initialDelay
// 如果堅(jiān)持要整點(diǎn)開始,建議:
@Scheduled(cron = "0 */5 * * * ?")
public void syncCustody() {
// 這種會(huì)固定在 :00, :05, :10 執(zhí)行
}
// 如果要從啟動(dòng)時(shí)間算,每5分鐘:
@Scheduled(fixedRate = 5 * 60 * 1000)
public void syncCustody2() {
// 從啟動(dòng)開始算,每5分鐘執(zhí)行
// 首次執(zhí)行是啟動(dòng)后立即執(zhí)行,除非配合 initialDelay
}
}配置建議:
# application.yml
scheduling:
tasks:
custody-sync:
# 從配置讀取,方便不同環(huán)境調(diào)整
fixed-rate: 300000 # 5分鐘
initial-delay: ${SYNC_INITIAL_DELAY:120000} # 默認(rèn)2分鐘
enabled: true6. 注意事項(xiàng)
時(shí)區(qū)問題:cron 表達(dá)式默認(rèn)使用服務(wù)器時(shí)區(qū),建議顯式指定
@Scheduled(cron = "0 0 9 * * ?", zone = "Asia/Shanghai")
任務(wù)重疊問題:
fixedRate可能重疊,使用@Async或調(diào)整線程池fixedDelay保證不重疊
異常處理:
- 任務(wù)異常不會(huì)影響后續(xù)調(diào)度
- 建議在方法內(nèi)部處理異常
應(yīng)用集群部署:
- 所有節(jié)點(diǎn)都會(huì)執(zhí)行定時(shí)任務(wù)
- 需要使用分布式鎖或任務(wù)調(diào)度中間件(如XXL-JOB)
根據(jù)你的具體需求,我建議:
- 如果需要嚴(yán)格的固定時(shí)間點(diǎn) → 用 cron
- 如果需要固定頻率且不關(guān)心重疊 → 用 fixedRate
- 如果需要保證任務(wù)串行 → 用 fixedDelay
- 如果需要延遲啟動(dòng) → 配合 initialDelay
到此這篇關(guān)于Spring @Scheduled中這些參數(shù)的區(qū)別、組合和應(yīng)用場(chǎng)景解析的文章就介紹到這了,更多相關(guān)SpringBoot Scheduled用法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot之@Scheduled注解用法解讀
- SpringBoot中@Scheduled實(shí)現(xiàn)服務(wù)啟動(dòng)時(shí)執(zhí)行一次
- 如何解決SpringBoot定時(shí)任務(wù)報(bào)錯(cuò)Unexpected error occurred in scheduled task問題
- SpringBoot使用@Scheduled實(shí)現(xiàn)定時(shí)任務(wù)的并行執(zhí)行
- Springboot中@scheduled注解解析
- SpringBoot中@Scheduled()注解以及cron表達(dá)式詳解
- SpringBoot中定時(shí)任務(wù)@Scheduled的多線程使用詳解
- SpringBoot通過@Scheduled實(shí)現(xiàn)定時(shí)任務(wù)及單線程運(yùn)行問題解決
- SpringBoot?ScheduledTaskRegistrar解決動(dòng)態(tài)定時(shí)任務(wù)思路詳解
- SpringBoot中定時(shí)任務(wù)@Scheduled注解的使用解讀
相關(guān)文章
Java SpringBoot集成ChatGPT實(shí)現(xiàn)AI聊天
ChatGPT已經(jīng)組件放開了,現(xiàn)在都可以基于它寫插件了,也許可以用它結(jié)合文字語音開發(fā)一個(gè)老人小孩需要的智能的說話陪伴啥的,這篇文章就介紹SpringBoot結(jié)合ChatGPT實(shí)現(xiàn)AI聊天感興趣的同學(xué)可以借鑒一下2023-04-04
SpringBoot結(jié)果封裝和異常攔截的實(shí)現(xiàn)示例
SpringBoot 項(xiàng)目中,我們通常需要將結(jié)果數(shù)據(jù)封裝成特定的格式,以方便客戶端進(jìn)行處理,本文主要介紹了SpringBoot?優(yōu)雅的結(jié)果封裝和異常攔截,感興趣的可以了解一下2023-08-08
Java實(shí)現(xiàn)字符串轉(zhuǎn)為駝峰格式的方法詳解
這篇文章主要介紹了如何利用Java語言實(shí)現(xiàn)字符串轉(zhuǎn)為駝峰格式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-07-07
SpringBoot整合Scala構(gòu)建Web服務(wù)的方法
這篇文章主要介紹了SpringBoot整合Scala構(gòu)建Web服務(wù)的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03

