Spring內(nèi)置定時(shí)任務(wù)調(diào)度@Scheduled使用詳解
Spring提供了@Scheduled注解用于定時(shí)任務(wù)。
一、@Scheduled的基本使用
啟用調(diào)度支持:@EnableScheduling
可以將@Scheduled注釋與觸發(fā)器元數(shù)據(jù)一起添加到方法中。例如,以下方法每隔5秒調(diào)用一次,并具有固定的延遲,這意味著周期是從前面每次調(diào)用的完成時(shí)間開始計(jì)算的
@Scheduled(fixedDelay=5000)
public void doSomething() {
// something that should execute periodically
}
如果需要固定速率執(zhí)行,可以更改批注中指定的屬性名。以下方法每5秒調(diào)用一次(在每次調(diào)用的連續(xù)開始時(shí)間之間計(jì)算)
@Scheduled(fixedRate=5000)
public void doSomething() {
// something that should execute periodically
}
對于固定延遲和固定速率任務(wù),可以通過指示在首次執(zhí)行方法之前要等待的毫秒數(shù)來指定初始延遲
@Scheduled(initialDelay=1000, fixedRate=5000)
public void doSomething() {
// something that should execute periodically
}
如果簡單的周期性調(diào)度不夠表達(dá),可以提供cron表達(dá)式。例如,以下命令僅在工作日執(zhí)行:
@Scheduled(cron="*/5 * * * * MON-FRI")
public void doSomething() {
// something that should execute on weekdays only
}
實(shí)現(xiàn)SchedulingConfigurer接口,重寫configureTasks方法:
@Schedule注解的一個(gè)缺點(diǎn)就是其定時(shí)時(shí)間不能動(dòng)態(tài)更改,它適用于具有固定任務(wù)周期的任務(wù),若要修改任務(wù)執(zhí)行周期,只能走“停服務(wù)→修改任務(wù)執(zhí)行周期→重啟服務(wù)”這條路。而基于 SchedulingConfigurer 接口方式可以做到。SchedulingConfigurer 接口可以實(shí)現(xiàn)在@Configuration等注解類上。
ScheduledTaskRegistrar類包括以下幾個(gè)重要方法:
void addTriggerTask(Runnable task, Trigger trigger)
void addTriggerTask(TriggerTask task)
void addCronTask(Runnable task, String expression)
void addCronTask(CronTask task)
void addFixedRateTask(Runnable task, long interval)
void addFixedRateTask(IntervalTask task)
void addFixedDelayTask(Runnable task, long delay)
void addFixedDelayTask(IntervalTask task)
具體實(shí)現(xiàn)參考如下:
@Component public class TestTask implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.addTriggerTask(new Runnable() { @Override public void run() { // 定時(shí)任務(wù)要執(zhí)行的內(nèi)容 System.out.println("【開始執(zhí)行定時(shí)任務(wù)。。?!?); } }, new Trigger() { @Override public Date nextExecutionTime(TriggerContext triggerContext) { // 定時(shí)任務(wù)觸發(fā),可修改定時(shí)任務(wù)的執(zhí)行周期 String cron = "0 0/5 * * * ?"; //可以將表達(dá)式配置在數(shù)據(jù)庫中 CronTrigger trigger = new CronTrigger(cron); Date nextExecDate = trigger.nextExecutionTime(triggerContext); return nextExecDate; } }); } }
提示:如果在數(shù)據(jù)庫修改時(shí)格式出現(xiàn)錯(cuò)誤,則定時(shí)任務(wù)會(huì)停止,即使重新修改正確;此時(shí)只能重新啟動(dòng)項(xiàng)目才能恢復(fù)。
二、使用@Scheduled注意事項(xiàng)
- spring的注解@Scheduled 需要寫在實(shí)現(xiàn)方法上;
- 定時(shí)器的任務(wù)方法不能有返回值(如果有返回值,spring初始化的時(shí)候會(huì)告訴你有個(gè)錯(cuò)誤、需要設(shè)定一個(gè)proxytargetclass的某個(gè)值為true),不能指向任何的參數(shù);
- 如果該方法需要與應(yīng)用程序上下文的其他對象進(jìn)行交互,通常是通過依賴注入來實(shí)現(xiàn);
- 實(shí)現(xiàn)類上要有組件的注解@Component。
三、使用@Scheduled常見問題
單線程任務(wù)丟失,轉(zhuǎn)為異步線程池
默認(rèn)的 ConcurrentTaskScheduler 計(jì)劃執(zhí)行器采用Executors.newSingleThreadScheduledExecutor() 實(shí)現(xiàn)單線程的執(zhí)行器。因此,對同一個(gè)調(diào)度任務(wù)的執(zhí)行總是同一個(gè)線程。如果任務(wù)的執(zhí)行時(shí)間超過該任務(wù)的下一次執(zhí)行時(shí)間,則會(huì)出現(xiàn)任務(wù)丟失,跳過該段時(shí)間的任務(wù)。上述問題有以下解決辦法:
采用異步的方式執(zhí)行調(diào)度任務(wù),配置 Spring 的 @EnableAsync,在執(zhí)行定時(shí)任務(wù)的方法上標(biāo)注 @Async配置任務(wù)執(zhí)行池,線程池大小 n 的數(shù)量為 單個(gè)任務(wù)執(zhí)行所需時(shí)間 / 任務(wù)執(zhí)行的間隔時(shí)間。如下:
//每30秒執(zhí)行一次 @Async("taskExecutor") @Scheduled(fixedRate = 1000 * 3) public void reportCurrentTime(){ System.out.println ("線程" + Thread.currentThread().getName() + "開始執(zhí)行定時(shí)任務(wù)===&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&7&&&====》" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); long start = System.currentTimeMillis(); }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot?整合?EasyExcel?實(shí)現(xiàn)自由導(dǎo)入導(dǎo)出功能
在實(shí)際的業(yè)務(wù)系統(tǒng)開發(fā)過程中,操作 Excel 實(shí)現(xiàn)數(shù)據(jù)的導(dǎo)入導(dǎo)出基本上是個(gè)非常常見的需求,這篇文章主要介紹了SpringBoot?整合?EasyExcel?實(shí)現(xiàn)自由導(dǎo)入導(dǎo)出功能,需要的朋友可以參考下2024-06-06Java數(shù)據(jù)脫敏實(shí)現(xiàn)的方法總結(jié)
數(shù)據(jù)脫敏,指的是對某些敏感信息通過脫敏規(guī)則進(jìn)行數(shù)據(jù)的變形,實(shí)現(xiàn)敏感隱私數(shù)據(jù)的可靠保護(hù),本文主要是對后端數(shù)據(jù)脫敏實(shí)現(xiàn)的簡單總結(jié),希望對大家有所幫助2023-07-07Springboot容器級后置處理器BeanDefinitionRegistryPostProcessor
這篇文章主要介紹了Springboot容器級后置處理器BeanDefinitionRegistryPostProcessor,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-01-01Collections.shuffle()方法實(shí)例解析
這篇文章主要介紹了Collections.shuffle()方法實(shí)例解析,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01SpringCloud2020.0.x版UnderTow AccessLog相關(guān)配置簡介
本文詳細(xì)介紹了SpringCloud中AccessLog的相關(guān)配置,我們可以根據(jù)文中的相關(guān)數(shù)據(jù)配置出所需的AccessLog的信息以及格式,感興趣的小伙伴可以參考一下2021-08-08Maven包沖突導(dǎo)致NoSuchMethodError錯(cuò)誤的解決辦法
web 項(xiàng)目 能正常編譯,運(yùn)行時(shí)也正常啟動(dòng),但執(zhí)行到需要調(diào)用 org.codehaus.jackson 包中的某個(gè)方法時(shí),產(chǎn)生運(yùn)行異常,這篇文章主要介紹了Maven包沖突導(dǎo)致NoSuchMethodError錯(cuò)誤的解決辦法,需要的朋友可以參考下2024-05-05