Spring @Scheduled注解及工作原理
1.@Scheduled注解定義
簡(jiǎn)單來說, @Scheduled是 Spring 提供的一個(gè)注解,用于在方法上標(biāo)記定時(shí)任務(wù)。通過它,我們可以輕松地在指定的時(shí)間間隔或特定的時(shí)間點(diǎn)執(zhí)行某些代碼,而不需要引入額外的定時(shí)任務(wù)庫(kù)。
舉個(gè)例子:
假設(shè)你有一個(gè)方法需要每隔5分鐘執(zhí)行一次,你只需要在方法上加上 @Scheduled注解,并設(shè)置相應(yīng)的屬性即可。
2.配置 @Scheduled
在開始使用 @Scheduled 之前,我們需要做一些配置工作。首先,確保你的 Spring 項(xiàng)目中引入了 spring-boot-starter,因?yàn)樗呀?jīng)包含了必要的依賴。
2.1 開啟定時(shí)任務(wù)支持
在你的主類(通常標(biāo)注了 @SpringBootApplication 的類)上添加@EnableScheduling注解,以啟用定時(shí)任務(wù)的支持。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class ScheduledDemoApplication {
public static void main(String[] args) {
SpringApplication.run(ScheduledDemoApplication.class, args);
}
}2.2 創(chuàng)建定時(shí)任務(wù)
接下來,我們創(chuàng)建一個(gè)服務(wù)類,并在其中定義一個(gè)定時(shí)任務(wù)方法。例如,每隔5秒打印一條消息:
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTasks {
@Scheduled(fixedRate = 5000)
public void reportCurrentTime() {
System.out.println("每5秒執(zhí)行一次任務(wù),當(dāng)前時(shí)間:" + System.currentTimeMillis());
}
}3. 常用屬性
@Scheduled 注解提供了多種方式來配置定時(shí)任務(wù)的執(zhí)行時(shí)間,主要包括以下幾種
3.1 fixedRate
指定一個(gè)固定的時(shí)間間隔,以毫秒為單位,表示上一次任務(wù)開始執(zhí)行后,多久再次執(zhí)行。
@Scheduled(fixedRate = 5000) // 每5秒執(zhí)行一次
public void fixedRateTask() {
System.out.println("Fixed Rate Task - " + System.currentTimeMillis());
}3.2 fixedDelay
指定一個(gè)固定的時(shí)間間隔,表示上一次任務(wù)執(zhí)行完成后,等待多久再次執(zhí)行。
@Scheduled(fixedDelay = 5000) // 上一次任務(wù)完成后5秒執(zhí)行一次
public void fixedDelayTask() {
System.out.println("Fixed Delay Task - " + System.currentTimeMillis());
}3.3 cron
使用 cron 表達(dá)式確地指定任務(wù)的執(zhí)行時(shí)間。cron 表達(dá)式可以讓你定義復(fù)雜的時(shí)間計(jì)劃。
@Scheduled(cron = "0 0/1 * * * ?") // 每分鐘執(zhí)行一次
public void cronTask() {
System.out.println("Cron Task - " + System.currentTimeMillis());
}4.工作原理
了解了如何使用 @Scheduled,那么它背后到底是如何運(yùn)作的呢?讓我們來深入探討一下。
4.1 基于TaskScheduler
Spring 的定時(shí)任務(wù)是基于 TaskScheduler 接口實(shí)現(xiàn)的。當(dāng)我們?cè)诜椒ㄉ鲜褂?@Scheduled 注解時(shí),Spring 會(huì)自動(dòng)為其創(chuàng)建一個(gè)調(diào)度器,并按照我們定義的時(shí)間計(jì)劃來執(zhí)行任務(wù)
4.2 使用 ThreadPoolTaskScheduler
默認(rèn)情況下,Spring 使用 ThreadPoolTaskScheduler 作為TaskScheduler的實(shí)現(xiàn)類。它內(nèi)部維護(hù)了一個(gè)線程池,用于執(zhí)行定時(shí)任務(wù)。這樣可以確保多個(gè)定時(shí)任務(wù)能夠并發(fā)執(zhí)行,而不會(huì)阻塞主線程。
注意: 如果你的應(yīng)用中有多個(gè)定時(shí)任務(wù),或者某些任務(wù)執(zhí)行時(shí)間較長(zhǎng),建議自定義ThreadPoolTaskScheduler的線程池大小,以避免任務(wù)堆積或資源浪費(fèi)。
4.3 定時(shí)任務(wù)的執(zhí)行流程
1、初始化階段:啟動(dòng) Spring 應(yīng)用時(shí),@EnableScheduling 注解會(huì)觸發(fā) Spring 的配置,掃描所有被 @Scheduled 注解標(biāo)記的方法。
2、注冊(cè)任務(wù):所有符合條件的定時(shí)任務(wù)方法會(huì)被注冊(cè)到 TaskScheduler 中。
3、執(zhí)行任務(wù):根據(jù)配置的時(shí)間計(jì)劃,TaskScheduler 會(huì)調(diào)度并在合適的線程中執(zhí)行相應(yīng)的任務(wù)方法。
5. 延時(shí)執(zhí)行的定時(shí)任務(wù)
為了更好地理解 @Scheduled 的使用,我們來實(shí)現(xiàn)一個(gè)稍微復(fù)雜些的示例——延時(shí)執(zhí)行任務(wù)。假設(shè)我們有一個(gè)任務(wù)需要在應(yīng)用啟動(dòng)后延時(shí)10秒執(zhí)行一次,然后每隔5秒重復(fù)執(zhí)行。
5.1 創(chuàng)建定時(shí)任務(wù)類
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
publicclass DelayedScheduledTasks {
privateboolean firstRun = true;
@Scheduled(fixedRate = 5000, initialDelay = 10000)
public void delayedTask() {
if (firstRun) {
System.out.println("延時(shí)10秒后首次執(zhí)行任務(wù),當(dāng)前時(shí)間:" + System.currentTimeMillis());
firstRun = false;
} else {
System.out.println("每5秒執(zhí)行一次任務(wù),當(dāng)前時(shí)間:" + System.currentTimeMillis());
}
}
}5.2 解釋
fixedRate = 5000: 任務(wù)每5秒執(zhí)行一次。initialDelay = 10000: 應(yīng)用啟動(dòng)后,延時(shí)10秒首次執(zhí)行任務(wù)。
6.自定義TaskScheduler
有時(shí)候,默認(rèn)的 ThreadPoolTaskScheduler 可能無法滿足我們的需求,比如需要更高的并發(fā)能力或特定的線程名稱模式。這時(shí)候,我們可以自定義一個(gè) TaskScheduler Bean。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@Configuration
publicclass SchedulerConfig {
@Bean
public ThreadPoolTaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(10); // 設(shè)置線程池大小
scheduler.setThreadNamePrefix("MyScheduler-"); // 設(shè)置線程名稱前綴
scheduler.initialize();
return scheduler;
}
}通過上述配置,我們創(chuàng)建了一個(gè)擁有10個(gè)線程的線程池,并為每個(gè)線程命名,方便日志追蹤和調(diào)試。
到此這篇關(guān)于Spring @Scheduled注解詳解的文章就介紹到這了,更多相關(guān)Spring @Scheduled注解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Spring?@Scheduled定時(shí)器注解使用方式
- Spring自帶定時(shí)任務(wù)@Scheduled注解實(shí)例講解
- Spring定時(shí)任務(wù)@Scheduled注解(cron表達(dá)式fixedRate?fixedDelay)
- Spring中@Scheduled注解的參數(shù)詳解
- Springboot中@scheduled注解解析
- SpringBoot中@Scheduled()注解以及cron表達(dá)式詳解
- Spring 定時(shí)任務(wù)@Scheduled 注解中的 Cron 表達(dá)式詳解
- spring-boot通過@Scheduled配置定時(shí)任務(wù)及定時(shí)任務(wù)@Scheduled注解的方法
- 詳解在Spring3中使用注解(@Scheduled)創(chuàng)建計(jì)劃任務(wù)
相關(guān)文章
淺談java中replace()和replaceAll()的區(qū)別
這篇文章主要介紹了java中replace()和replaceAll()的區(qū)別,兩者都是常用的替換字符的方法,感興趣的小伙伴們可以參考一下2015-11-11
查看vscode中JDK版本的兩個(gè)簡(jiǎn)單方法小結(jié)
這篇文章主要介紹了查看vscode中JDK版本的兩個(gè)簡(jiǎn)單方法,分別是通過命令面板或資源管理器Explorer來查找和設(shè)置JDK版本,包括具體步驟和操作說明,需要的朋友可以參考下2025-05-05
基于SpringCloudAlibaba+Skywalking的全鏈路監(jiān)控設(shè)計(jì)方案
這篇文章主要介紹了基于SpringCloudAlibaba+Skywalking的全鏈路監(jiān)控設(shè)計(jì)方案,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-01-01
Spring Boot中使用RabbitMQ 生產(chǎn)消息和消費(fèi)消息的實(shí)例代碼
本文介紹了在SpringBoot中如何使用RabbitMQ進(jìn)行消息的生產(chǎn)和消費(fèi),詳細(xì)闡述了RabbitMQ中交換機(jī)的作用和類型,包括直連交換機(jī)、主題交換機(jī)、扇出交換機(jī)和頭交換機(jī),并解釋了各自的消息路由機(jī)制,感興趣的朋友一起看看吧2024-10-10
Tk.mybatis零sql語(yǔ)句實(shí)現(xiàn)動(dòng)態(tài)sql查詢的方法(4種)
有時(shí)候,查詢數(shù)據(jù)需要根據(jù)條件使用動(dòng)態(tài)查詢,這時(shí)候需要使用動(dòng)態(tài)sql,本文主要介紹了Tk.mybatis零sql語(yǔ)句實(shí)現(xiàn)動(dòng)態(tài)sql查詢的方法,感興趣的可以了解一下2021-12-12
使用easyexcel導(dǎo)出的excel文件,使用poi讀取時(shí)異常處理方案
這篇文章主要介紹了使用easyexcel導(dǎo)出的excel文件,使用poi讀取時(shí)異常處理方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12

