最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot的@Scheduled和@Schedules的用法及區(qū)別介紹

 更新時(shí)間:2026年05月08日 15:17:14   作者:qwert1037  
文章詳細(xì)解析了Spring框架中`@Scheduled`注解的用法,包括Cron表達(dá)式、fixedRate、fixedDelay、initialDelay等參數(shù)的使用方法及場(chǎng)景選擇,還介紹了如何啟用定時(shí)任務(wù)、自定義TaskScheduler、錯(cuò)誤處理、最佳實(shí)踐及常見(jiàn)問(wèn)題解決方法,并通過(guò)案例展示了如何配置定時(shí)任務(wù)

@Scheduled 的詳細(xì)解析

參數(shù)詳解

cron:使用Cron表達(dá)式來(lái)指定復(fù)雜的調(diào)度模式。

Cron表達(dá)式的格式如下:

  • 秒(0-59)
  • 分鐘(0-59)
  • 小時(shí)(0-23)
  • 日(1-31)
  • 月(1-12 或 JAN-DEC)
  • 星期(0-7 或 SUN-SAT,其中0和7都表示星期日)
  • 年(可選,1970-2099)

Cron表達(dá)式的每個(gè)字段可以是具體的值、范圍、列表或通配符(*)。

例如:

  • "0 0 12 * * ?"表示每天中午12點(diǎn)。
  • "0 15 10 ? * MON-FRI"表示周一至周五上午10:15執(zhí)行。
  • "0 0/5 * * * ?"表示每5分鐘執(zhí)行一次。
  • "0 0 12 1 * ?"表示每月第一天中午12點(diǎn)執(zhí)行。

fixedRate:指定以固定的速率重復(fù)執(zhí)行任務(wù),從前一次任務(wù)開(kāi)始時(shí)刻算起。它不會(huì)等待前一個(gè)任務(wù)完成,因此如果任務(wù)執(zhí)行時(shí)間超過(guò)了設(shè)定的時(shí)間間隔,可能會(huì)有重疊的任務(wù)實(shí)例在運(yùn)行。

fixedDelay:類似于 fixedRate,但是它是以前一次任務(wù)的完成時(shí)刻作為下一次任務(wù)啟動(dòng)的時(shí)間基準(zhǔn)。這種方式可以確保每次只有一個(gè)任務(wù)實(shí)例在運(yùn)行,前提是任務(wù)的執(zhí)行時(shí)間短于延遲時(shí)間。

initialDelay:在第一次執(zhí)行之前等待的時(shí)間(毫秒)。這個(gè)參數(shù)通常與 fixedRatefixedDelay 一起使用,用來(lái)設(shè)置首次執(zhí)行前的延遲。

zone:定義時(shí)區(qū),默認(rèn)是系統(tǒng)的默認(rèn)時(shí)區(qū)。如果你的應(yīng)用需要在全球不同地區(qū)運(yùn)行,明確指定時(shí)區(qū)可能是很重要的。

Cron表達(dá)式、fixedRate、fixedDelay、initialDelay如何選擇

  • 如果你需要非常具體的調(diào)度模式,如每天凌晨?jī)牲c(diǎn)執(zhí)行某個(gè)任務(wù),那么應(yīng)該選擇Cron表達(dá)式。
  • 如果你希望任務(wù)以固定的速率重復(fù)執(zhí)行,不論每次執(zhí)行花費(fèi)多少時(shí)間,你應(yīng)該選擇fixedRate
  • 如果你希望在前一個(gè)任務(wù)完全結(jié)束后再等待一段固定時(shí)間才開(kāi)始下一個(gè)任務(wù),那么fixedDelay是更好的選擇。
  • 如果你需要設(shè)置首次執(zhí)行的延遲,可以添加initialDelay參數(shù)到你的調(diào)度配置中。

示例代碼:

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTasks {

    // 每天中午12點(diǎn)執(zhí)行(上海時(shí)區(qū))
    @Scheduled(cron = "0 0 12 * * ?", zone = "Asia/Shanghai")
    public void scheduledTaskUsingCron() {
        System.out.println("Scheduled task using cron at Asia/Shanghai timezone.");
    }

    // 每5秒執(zhí)行一次,首次執(zhí)行前等待2秒
    @Scheduled(fixedRate = 5000, initialDelay = 2000)
    public void scheduledTaskWithFixedRate() {
        System.out.println("Scheduled task with fixed rate.");
    }

    // 上次任務(wù)完成后等待3秒再執(zhí)行下一次
    @Scheduled(fixedDelay = 3000)
    public void scheduledTaskWithFixedDelay() {
        System.out.println("Scheduled task with fixed delay.");
    }
}

@Schedules 的詳細(xì)解析

@Schedules 允許多個(gè) @Scheduled 注解組合在一起,為同一個(gè)方法設(shè)定多種不同的調(diào)度策略。

這對(duì)于那些需要在多個(gè)不同時(shí)間點(diǎn)或條件下觸發(fā)的方法非常有用。

示例代碼:

import org.springframework.scheduling.annotation.Schedules;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class MultipleScheduledTasks {

    // 每天中午12點(diǎn)執(zhí)行,并且每5秒也執(zhí)行一次
    @Schedules({
        @Scheduled(cron = "0 0 12 * * ?"),
        @Scheduled(fixedRate = 5000)
    })
    public void multipleScheduledTasks() {
        System.out.println("Multiple scheduled tasks.");
    }
}

啟用和管理定時(shí)任務(wù)

要使這些注解生效,你需要確保你的Spring應(yīng)用已經(jīng)啟用了對(duì)它們的支持。

這可以通過(guò)在配置類上添加 @EnableScheduling 來(lái)實(shí)現(xiàn):

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

@Configuration
@EnableScheduling
public class SchedulingConfig {
    // 配置類內(nèi)容
}

自定義 TaskScheduler

對(duì)于更復(fù)雜的需求,比如調(diào)整線程池大小或者設(shè)置線程名稱前綴等,你可以通過(guò)自定義 TaskScheduler 來(lái)進(jìn)行配置。

Spring提供了幾種內(nèi)置的調(diào)度器實(shí)現(xiàn),如 ThreadPoolTaskSchedulerConcurrentTaskScheduler。

示例代碼:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

@Configuration
public class SchedulerConfig {

    @Bean
    public ThreadPoolTaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(10); // 設(shè)置線程池大小
        taskScheduler.setThreadNamePrefix("MyScheduledTask-");
        taskScheduler.setErrorHandler(t -> {
            System.err.println("Error occurred in scheduled task: " + t.getMessage());
        });
        taskScheduler.setWaitForTasksToCompleteOnShutdown(true);
        taskScheduler.setAwaitTerminationSeconds(60);
        return taskScheduler;
    }
}

錯(cuò)誤處理

當(dāng)一個(gè)預(yù)定任務(wù)拋出異常時(shí),默認(rèn)情況下Spring會(huì)記錄錯(cuò)誤日志,但任務(wù)本身不會(huì)被取消。

如果你想改變這種行為,可以使用 DelegatingErrorHandlingRunnable 或者直接在 ThreadPoolTaskScheduler 中設(shè)置錯(cuò)誤處理器(如上面的示例所示)。

自定義錯(cuò)誤處理邏輯

你可以創(chuàng)建自己的錯(cuò)誤處理器來(lái)捕獲并處理異常:

import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

@Configuration
public class AsyncConfig implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(5);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("Async-");
        executor.initialize();
        return executor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SimpleAsyncUncaughtExceptionHandler() {
            @Override
            public void handleUncaughtException(Throwable ex, Method method, Object... params) {
                // 自定義異常處理邏輯
                System.err.println("Exception in async task: " + ex.getMessage());
            }
        };
    }
}

最佳實(shí)踐

  • 避免長(zhǎng)時(shí)間運(yùn)行的任務(wù):盡量不要讓預(yù)定任務(wù)執(zhí)行過(guò)長(zhǎng)的時(shí)間,因?yàn)樗鼈兛赡軙?huì)阻塞其他任務(wù)的執(zhí)行。如果任務(wù)有可能運(yùn)行很長(zhǎng)時(shí)間,請(qǐng)考慮將其拆分為更小的部分,或者使用異步處理。
  • 任務(wù)沖突管理:當(dāng)使用 fixedRate 時(shí),要注意任務(wù)可能會(huì)重疊。如果任務(wù)執(zhí)行時(shí)間可能超過(guò)間隔時(shí)間,應(yīng)該選擇 fixedDelay 來(lái)避免這種情況。
  • 資源清理:確保在任務(wù)結(jié)束時(shí)正確釋放任何獲取的資源,比如數(shù)據(jù)庫(kù)連接或文件句柄。
  • 監(jiān)控和報(bào)警:建立適當(dāng)?shù)谋O(jiān)控和報(bào)警機(jī)制,以便在任務(wù)失敗時(shí)能夠及時(shí)收到通知并采取行動(dòng)。可以利用Spring Boot Actuator提供的健康檢查端點(diǎn),或者集成第三方監(jiān)控工具如Prometheus、Grafana等。
  • 冪等性設(shè)計(jì):確保任務(wù)邏輯具有冪等性,即多次執(zhí)行相同的任務(wù)不會(huì)導(dǎo)致不一致的結(jié)果。這在分布式環(huán)境中尤為重要。
  • 日志記錄:為每個(gè)任務(wù)添加詳細(xì)的日志記錄,包括任務(wù)開(kāi)始時(shí)間和結(jié)束時(shí)間,以便追蹤任務(wù)執(zhí)行情況。
  • 測(cè)試:編寫(xiě)單元測(cè)試和集成測(cè)試來(lái)驗(yàn)證定時(shí)任務(wù)的行為是否符合預(yù)期??梢允褂肕ockito或其他測(cè)試框架模擬依賴服務(wù)。
  • 多實(shí)例部署的問(wèn)題:在多實(shí)例部署的情況下,所有的實(shí)例都會(huì)嘗試執(zhí)行相同的定時(shí)任務(wù),這可能導(dǎo)致數(shù)據(jù)競(jìng)爭(zhēng)或重復(fù)執(zhí)行。一種解決方案是使用分布式鎖,如Redisson提供的RedLock,來(lái)保證同一時(shí)間只有一個(gè)實(shí)例執(zhí)行特定的任務(wù)。
  • 性能優(yōu)化:對(duì)于高并發(fā)場(chǎng)景下的定時(shí)任務(wù),應(yīng)該評(píng)估線程池的大小和任務(wù)的執(zhí)行頻率,避免因過(guò)多的任務(wù)同時(shí)啟動(dòng)而導(dǎo)致資源耗盡??梢酝ㄟ^(guò)限流、隊(duì)列管理和異步處理等方式提高系統(tǒng)的穩(wěn)定性和響應(yīng)速度。

處理定時(shí)任務(wù)中的常見(jiàn)問(wèn)題

  • 任務(wù)未按預(yù)期執(zhí)行:檢查日志以確定是否有任何異?;蝈e(cuò)誤信息。確保任務(wù)方法是非靜態(tài)的,并且沒(méi)有被final修飾。確認(rèn) @EnableScheduling 已經(jīng)正確啟用。另外,檢查是否存在其他因素阻止任務(wù)執(zhí)行,如網(wǎng)絡(luò)延遲或依賴服務(wù)不可用。
  • 任務(wù)執(zhí)行順序混亂:如果你有多個(gè)任務(wù)幾乎同時(shí)執(zhí)行,可能會(huì)出現(xiàn)執(zhí)行順序混亂的情況。確保你理解了 fixedRatefixedDelay 的區(qū)別,并根據(jù)需要選擇合適的方式。此外,可以通過(guò)增加任務(wù)之間的最小間隔時(shí)間來(lái)減少?zèng)_突的可能性。
  • 多實(shí)例部署的問(wèn)題:在多實(shí)例部署的情況下,所有實(shí)例都會(huì)嘗試執(zhí)行相同的定時(shí)任務(wù)。為了解決這個(gè)問(wèn)題,可以引入分布式鎖機(jī)制,如基于Redis的鎖或Zookeeper的臨時(shí)節(jié)點(diǎn),以確保同一時(shí)間只有一個(gè)實(shí)例執(zhí)行任務(wù)。
  • 長(zhǎng)時(shí)間運(yùn)行的任務(wù):盡量不要讓預(yù)定任務(wù)執(zhí)行過(guò)長(zhǎng)的時(shí)間,因?yàn)樗鼈兛赡軙?huì)阻塞其他任務(wù)的執(zhí)行。如果任務(wù)有可能運(yùn)行很長(zhǎng)時(shí)間,請(qǐng)考慮將其拆分為更小的部分,或者使用異步處理,如通過(guò)消息隊(duì)列(MQ)來(lái)分發(fā)任務(wù)。
  • 時(shí)區(qū)問(wèn)題:確保你的應(yīng)用程序正確處理時(shí)區(qū)差異,特別是在全球范圍內(nèi)運(yùn)行時(shí)??梢栽?@Scheduled 注解中顯式指定 zone 參數(shù),或者在整個(gè)應(yīng)用程序中統(tǒng)一配置默認(rèn)時(shí)區(qū)。

案例分析

假設(shè)你正在開(kāi)發(fā)一個(gè)電子商務(wù)平臺(tái),需要每天凌晨2點(diǎn)生成前一天的銷售報(bào)告。

你可以使用 @Scheduled 注解來(lái)安排這個(gè)任務(wù):

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service
public class DailyReportService {

    @Scheduled(cron = "0 0 2 * * ?", zone = "Asia/Shanghai")
    public void generateDailySalesReport() {
        // 執(zhí)行生成銷售報(bào)告的邏輯
        System.out.println("Generating daily sales report at Asia/Shanghai timezone.");
    }
}

此外,你還可以結(jié)合上述的最佳實(shí)踐來(lái)增強(qiáng)任務(wù)的可靠性,例如:

  • 確保任務(wù)具有冪等性,即使由于某種原因任務(wù)重復(fù)執(zhí)行也不會(huì)影響結(jié)果。
  • 添加詳細(xì)的日志記錄,幫助追蹤任務(wù)的執(zhí)行情況。
  • 實(shí)現(xiàn)錯(cuò)誤處理邏輯,確保即使發(fā)生異常也能得到妥善處理。
  • 如果平臺(tái)有多實(shí)例部署,考慮使用分布式鎖來(lái)防止多個(gè)實(shí)例同時(shí)生成報(bào)告。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java匿名類,匿名內(nèi)部類實(shí)例分析

    Java匿名類,匿名內(nèi)部類實(shí)例分析

    這篇文章主要介紹了Java匿名類,匿名內(nèi)部類,結(jié)合實(shí)例形式分析了Java匿名類,匿名內(nèi)部類相關(guān)原理、用法及操作注意事項(xiàng),需要的朋友可以參考下
    2020-04-04
  • SpringBoot使用redis生成訂單號(hào)的實(shí)現(xiàn)示例

    SpringBoot使用redis生成訂單號(hào)的實(shí)現(xiàn)示例

    在電商系統(tǒng)中,生成唯一訂單號(hào)是常見(jiàn)需求,本文介紹如何利用SpringBoot和Redis實(shí)現(xiàn)訂單號(hào)的生成,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-09-09
  • 淺談spring-boot 允許接口跨域并實(shí)現(xiàn)攔截(CORS)

    淺談spring-boot 允許接口跨域并實(shí)現(xiàn)攔截(CORS)

    本篇文章主要介紹了淺談spring-boot 允許接口跨域并實(shí)現(xiàn)攔截(CORS),具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-08-08
  • Java實(shí)現(xiàn)監(jiān)控多個(gè)線程狀態(tài)的簡(jiǎn)單實(shí)例

    Java實(shí)現(xiàn)監(jiān)控多個(gè)線程狀態(tài)的簡(jiǎn)單實(shí)例

    下面小編就為大家?guī)?lái)一篇Java實(shí)現(xiàn)監(jiān)控多個(gè)線程狀態(tài)的簡(jiǎn)單實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-03-03
  • SpringBoot3.x打包Docker容器的實(shí)現(xiàn)

    SpringBoot3.x打包Docker容器的實(shí)現(xiàn)

    這篇文章主要介紹了SpringBoot3.x打包Docker容器的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • 關(guān)于工廠方法模式的Java實(shí)現(xiàn)

    關(guān)于工廠方法模式的Java實(shí)現(xiàn)

    這篇文章主要介紹了關(guān)于工廠方法模式的Java實(shí)現(xiàn)講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 詳解MyBatis增刪改查SQL案例實(shí)戰(zhàn)

    詳解MyBatis增刪改查SQL案例實(shí)戰(zhàn)

    本文通過(guò)具體的SQL案例,詳細(xì)介紹了MyBatis的增刪改查操作,通過(guò)靈活的Mapper接口和XML配置,MyBatis能夠?qū)崿F(xiàn)高效的數(shù)據(jù)操作,同時(shí)支持動(dòng)態(tài)SQL和批量操作,極大地提升了開(kāi)發(fā)效率,感興趣的可以了解一下
    2026-03-03
  • Spring BPP中如何優(yōu)雅的創(chuàng)建動(dòng)態(tài)代理Bean詳解

    Spring BPP中如何優(yōu)雅的創(chuàng)建動(dòng)態(tài)代理Bean詳解

    這篇文章主要給大家介紹了關(guān)于Spring BPP中如何優(yōu)雅的創(chuàng)建動(dòng)態(tài)代理Bean的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • SpringCloud之服務(wù)注冊(cè)與發(fā)現(xiàn)Spring Cloud Eureka實(shí)例代碼

    SpringCloud之服務(wù)注冊(cè)與發(fā)現(xiàn)Spring Cloud Eureka實(shí)例代碼

    這篇文章主要介紹了SpringCloud之服務(wù)注冊(cè)與發(fā)現(xiàn)Spring Cloud Eureka實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04
  • 舉例講解Java設(shè)計(jì)模式中的對(duì)象池模式編程

    舉例講解Java設(shè)計(jì)模式中的對(duì)象池模式編程

    這篇文章主要介紹了Java設(shè)計(jì)模式中的對(duì)象池模式編程示例分享,對(duì)象池模式經(jīng)常在多線程開(kāi)發(fā)時(shí)被用到,需要的朋友可以參考下
    2016-02-02

最新評(píng)論

清丰县| 和政县| 江陵县| 八宿县| 利川市| 邯郸市| 武平县| 屏东县| 芦溪县| 南投县| 绿春县| 法库县| 焦作市| 广河县| 肃南| 绍兴市| 镇雄县| 都昌县| 平邑县| 镇远县| 桐庐县| 荥阳市| 宜宾市| 鹿泉市| 杭锦旗| 阿尔山市| 白城市| 济阳县| 田东县| 文化| 腾冲县| 招远市| 体育| 蓬安县| 雅安市| 桦南县| 从化市| 剑河县| 潜江市| 齐齐哈尔市| 茶陵县|