Java定時任務(wù)Schedule的基本用法及Cron表達(dá)式實踐記錄
在日常Java開發(fā)中,定時任務(wù)是高頻需求場景,比如定時同步數(shù)據(jù)、定時清理日志、定時發(fā)送通知等。Spring框架提供的@Scheduled注解簡化了定時任務(wù)的開發(fā),無需依賴外部調(diào)度框架(如Quartz),就能快速實現(xiàn)輕量級定時任務(wù)。而cron表達(dá)式作為Schedule中靈活度最高的觸發(fā)規(guī)則配置方式,是掌握該功能的核心。本文將從Schedule的基礎(chǔ)用法入手,深入解析cron表達(dá)式,并結(jié)合實例演示其在項目中的應(yīng)用。
一、Spring Schedule基礎(chǔ)配置
要使用Spring Schedule,首先需要完成基礎(chǔ)配置,整體步驟簡單易懂,適用于Spring Boot項目和傳統(tǒng)Spring項目。
1.1 依賴引入(Spring Boot)
Spring Boot項目無需額外引入依賴,spring-boot-starter中已包含Schedule相關(guān)組件,只需確保pom.xml(Maven)中存在核心依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>1.2 開啟定時任務(wù)支持
在Spring Boot啟動類上添加@EnableScheduling注解,開啟定時任務(wù)調(diào)度功能:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling // 開啟定時任務(wù)
public class ScheduleDemoApplication {
public static void main(String[] args) {
SpringApplication.run(ScheduleDemoApplication.class, args);
}
}1.3 基礎(chǔ)定時任務(wù)實現(xiàn)
通過@Scheduled注解標(biāo)記方法為定時任務(wù),支持多種觸發(fā)規(guī)則,常見的有固定延遲、固定頻率和cron表達(dá)式三種方式。其中cron表達(dá)式適用于復(fù)雜的時間規(guī)則配置,也是本文重點。
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component // 交給Spring管理
public class ScheduleTask {
// 固定延遲:上一次任務(wù)執(zhí)行完畢后延遲1秒執(zhí)行下一次
@Scheduled(fixedDelay = 1000)
public void fixedDelayTask() {
System.out.println("固定延遲任務(wù)執(zhí)行:" + System.currentTimeMillis());
}
// 固定頻率:每隔1秒執(zhí)行一次(無論上一次是否完成)
@Scheduled(fixedRate = 1000)
public void fixedRateTask() {
System.out.println("固定頻率任務(wù)執(zhí)行:" + System.currentTimeMillis());
}
// cron表達(dá)式:每天凌晨2點執(zhí)行
@Scheduled(cron = "0 0 2 * * ?")
public void cronTask() {
System.out.println("Cron任務(wù)執(zhí)行:" + System.currentTimeMillis());
}
}二、Cron表達(dá)式深度解析
Cron表達(dá)式是一種時間表達(dá)式,用于定義復(fù)雜的定時規(guī)則,起源于Unix系統(tǒng),后被廣泛應(yīng)用于各類調(diào)度框架。在Spring Schedule中,cron表達(dá)式支持6個或7個字段,字段之間用空格分隔,語法格式如下:
2.1 表達(dá)式格式
Spring Schedule中的cron表達(dá)式格式(7個字段,最后一個年份字段可選):
秒 分 時 日 月 周 年(可選)
各字段的取值范圍及允許的特殊字符如下表所示:
字段 | 取值范圍 | 允許的特殊字符 | 說明 |
|---|---|---|---|
秒 | 0-59 | , - * / | 每秒用*表示,每5秒用0/5表示 |
分 | 0-59 | , - * / | 每分用*表示,每10分用0/10表示 |
時 | 0-23 | , - * / | 每天凌晨2點用2表示,每6小時用0/6表示 |
日 | 1-31 | , - * / ? L W C | ?表示不指定值,避免日和周沖突;L表示當(dāng)月最后一天 |
月 | 1-12 或 JAN-DEC | , - * / | 1表示1月,JAN也可表示1月 |
周 | 1-7 或 SUN-SAT | , - * / ? L C # | 1表示周日,7表示周六;#表示第幾個周幾,如6#3表示當(dāng)月第3個周五 |
年(可選) | 1970-2099 | , - * / | 省略時表示所有年份 |
2.2 特殊字符含義
cron表達(dá)式的靈活度依賴于特殊字符的使用,核心特殊字符的含義如下:
- *:表示匹配該字段的所有值。例如,時字段為*,表示每小時都觸發(fā)。
- ?:僅用于日和周字段,標(biāo)識不指定具體值,避免兩個字段沖突。例如,要指定每月10號觸發(fā),周字段需設(shè)為?
- /:表示遞增觸發(fā)。格式為“起始值/步長”,例如,秒字段為0/5,表示從0秒開始,每5秒觸發(fā)一次。
- -:表示區(qū)間。例如,時字段為9-17,表示上午9點到下午5點之間,每小時觸發(fā)一次。
- ,:表示多個值。例如,分字段為10,20,30,表示每小時的10分、20分、30分各觸發(fā)一次。
- L:僅用于日和周字段,標(biāo)識最后一個。例如,日字段為L,表示當(dāng)月最后一天;周字段為L,表示當(dāng)月最后一個周六。
- #:僅用于周字段,標(biāo)識第幾個周幾。格式為“周幾#第幾個”,例如,周字段為6#3,表示當(dāng)月第3個周五(6表示周五)。
2.3 常用Cron表達(dá)式示例
結(jié)合實際業(yè)務(wù)場景,整理以下常用cron表達(dá)式,可直接套用:
- 0 0 2 * * ?:每天凌晨2點執(zhí)行
- 0 30 8 * * ?:每天早上8點30分執(zhí)行
- 0 0/10 * * * ?:每10分鐘執(zhí)行一次
- 0 0 9-18 * * ?:每天上午9點到下午6點,每小時執(zhí)行一次
- 0 0 12 ? * SAT:每周六中午12點執(zhí)行
- 0 0 0 L * ?:每月最后一天凌晨0點執(zhí)行
- 0 0 0 1 * ?:每月1號凌晨0點執(zhí)行
- 0 0 0 ? * 6#1:每月第一個周五凌晨0點執(zhí)行
- 0/5 * * * * ?:每5秒執(zhí)行一次(用于測試)
三、Schedule進(jìn)階用法與注意事項
3.1 異步定時任務(wù)
默認(rèn)情況下,Spring Schedule的定時任務(wù)是同步執(zhí)行的,即多個任務(wù)會在同一個線程中按順序執(zhí)行,若某個任務(wù)執(zhí)行時間過長,會阻塞其他任務(wù)。如需異步執(zhí)行,可通過@EnableAsync和@Async注解實現(xiàn):
// 1. 啟動類添加@EnableAsync開啟異步支持
@SpringBootApplication
@EnableScheduling
@EnableAsync
public class ScheduleDemoApplication { ... }
// 2. 定時任務(wù)方法添加@Async注解
@Component
public class ScheduleTask {
@Async
@Scheduled(cron = "0/5 * * * * ?")
public void asyncCronTask() {
System.out.println("異步Cron任務(wù)執(zhí)行:" + Thread.currentThread().getName());
}
}3.2 動態(tài)調(diào)整Cron表達(dá)式
靜態(tài)cron表達(dá)式在項目啟動后無法修改,若需動態(tài)調(diào)整觸發(fā)規(guī)則,可通過實現(xiàn)SchedulingConfigurer接口自定義調(diào)度配置,從數(shù)據(jù)庫或配置中心讀取cron表達(dá)式:
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
@Component
public class DynamicCronTask implements SchedulingConfigurer {
// 模擬從數(shù)據(jù)庫獲取cron表達(dá)式(實際項目中可對接DB或Nacos)
private String cron = "0/5 * * * * ?";
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
// 注冊定時任務(wù)
taskRegistrar.addTriggerTask(
this::dynamicTaskExecute, // 任務(wù)執(zhí)行邏輯
triggerContext -> {
// 每次觸發(fā)前重新獲取cron表達(dá)式(實現(xiàn)動態(tài)更新)
CronTrigger trigger = new CronTrigger(getCron());
return trigger.nextExecutionTime(triggerContext);
}
);
}
public void dynamicTaskExecute() {
System.out.println("動態(tài)Cron任務(wù)執(zhí)行:" + System.currentTimeMillis());
}
// 獲取最新cron表達(dá)式(可擴展為從數(shù)據(jù)庫查詢)
public String getCron() {
return this.cron;
}
// 更新cron表達(dá)式
public void setCron(String cron) {
this.cron = cron;
}
}3.3 核心注意事項
- 日和周字段沖突:日和周字段不能同時指定具體值,需有一個設(shè)為?,否則會導(dǎo)致任務(wù)觸發(fā)規(guī)則異常。例如,要指定每月10號執(zhí)行,周字段必須設(shè)為?,表達(dá)式為0 0 0 10 * ?。
- 任務(wù)執(zhí)行時長:同步任務(wù)中,若任務(wù)執(zhí)行時長超過觸發(fā)間隔,下一次任務(wù)會等待上一次完成后再執(zhí)行;異步任務(wù)無此限制,但需注意并發(fā)問題。
- 時區(qū)問題:Spring Schedule默認(rèn)使用服務(wù)器時區(qū),若需指定時區(qū),可在
@Scheduled注解中設(shè)置zone屬性,例如zone = "GMT+8"。 - 避免耗時操作:定時任務(wù)中應(yīng)避免執(zhí)行耗時過長的操作,建議將耗時邏輯異步處理,或拆分任務(wù),防止阻塞調(diào)度線程。
到此這篇關(guān)于Java定時任務(wù)Schedule的基本用法及Cron表達(dá)式實踐的文章就介紹到這了,更多相關(guān)Java Schedule用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java覆蓋第三方j(luò)ar包中的某一個類的實現(xiàn)方法
在我們?nèi)粘5拈_發(fā)中,經(jīng)常需要使用第三方的 jar 包,有時候我們會發(fā)現(xiàn)第三方的 jar 包中的某一個類有問題,或者我們需要定制化修改其中的邏輯,那么應(yīng)該如何實現(xiàn)呢,本文給大家介紹了Java覆蓋第三方j(luò)ar包中的某一個類的實現(xiàn)方法,需要的朋友可以參考下2025-02-02
Java11中基于嵌套關(guān)系的訪問控制優(yōu)化詳解
Java(和其他語言)通過內(nèi)部類支持嵌套類,要使其正常工作,需要編譯器執(zhí)行一些技巧,下面這篇文章主要給大家介紹了關(guān)于Java11中基于嵌套關(guān)系的訪問控制優(yōu)化的相關(guān)資料,需要的朋友可以參考下2022-01-01
SpringBoot實現(xiàn)熱部署Community的示例代碼
本文主要介紹了SpringBoot實現(xiàn)熱部署Community的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06

