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

基于Spring定時(shí)任務(wù)的fixedRate和fixedDelay的區(qū)別

 更新時(shí)間:2021年10月18日 10:17:05   作者:隔葉黃鶯 Yanbin Blog  
這篇文章主要介紹了基于Spring定時(shí)任務(wù)的fixedRate和fixedDelay的區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Spring定時(shí)任務(wù)的fixedRate和fixedDelay區(qū)別

用過(guò) Spring 的 @EnableScheduling 的都知道,我們用三種形式來(lái)部署計(jì)劃任務(wù),即 @Scheduled 注解的 fixedRate(fixedRateString), fixedDelay(fixedDelayString), 以及 cron. cron 不在這里討論的范疇。我們著重在如何理解 fixedRate 和 fixedDelay 的區(qū)別。

在 Spring 的 Scheduled 注解的 JavaDoc 對(duì)此的解釋很簡(jiǎn)單

public abstract long fixedRate
Execute the annotated method with a fixed period in milliseconds between invocations.

public abstract long fixedDelay
Execute the annotated method with a fixed period in milliseconds between the end of the last invocation and the start of the next.

只是說(shuō)是 fixedRate 任務(wù)兩次執(zhí)行時(shí)間間隔是任務(wù)的開(kāi)始點(diǎn),而 fixedDelay 的間隔是前次任務(wù)的結(jié)束與下次任務(wù)的開(kāi)始。

大致用示意字符串來(lái)表示如下(每個(gè) T1, 或 T2 代表任務(wù)執(zhí)行秒數(shù)(每次任務(wù)執(zhí)行時(shí)間不定),假定 fixedRate 或 fixedDelay 的值是 5 秒,用 W 表示等待的數(shù))

fixedRate: T1.T1WWWT2.T2.T2WW.T3.T3.T3.T3.T3.T4.T4.T4.T4.T4.T4.T4T5T5WWWT6.T6........

fixedDelay: T1.T1.WWWWW.T2.T2.T2WWWWW.T3.T3.T3.T3.T3.WWWWW.T4.T4.T4.T4.T4.T4.T4.WWWWWT6.T6......

一般來(lái)說(shuō)能理解到上面兩個(gè)場(chǎng)景已經(jīng)差不多了,相比而言 fixedDelay 簡(jiǎn)單些,盯著上一次任務(wù)的屁股就行。

以前我對(duì) fixedRate 還有一個(gè)誤區(qū)就是,以為任務(wù)時(shí)長(zhǎng)超過(guò) fixedRate 時(shí)會(huì)啟動(dòng)多個(gè)任務(wù)實(shí)例,其實(shí)不會(huì); 只不過(guò)會(huì)在上次任務(wù)執(zhí)行完后立即啟動(dòng)下一輪。除非這個(gè) Job 方法用 @Async 注解了,使得任務(wù)不在 TaskScheduler 線程池中執(zhí)行,而是每次創(chuàng)建新線程來(lái)執(zhí)行。

具體理解我們可以用代碼來(lái)演示

@EnableScheduling
@SpringBootApplication
public class Application { 
    private AtomicInteger number = new AtomicInteger(); 
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
 
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(5);
        return taskScheduler;
    }
 
    @Scheduled(fixedRate = 5000)
    public void job() {
        LocalTime start = LocalTime.now();
        System.out.println(Thread.currentThread() + " start " + number.incrementAndGet() + " @ "  + start);
        try {
            Thread.sleep(ThreadLocalRandom.current().nextInt(15) * 1000);
        } catch (InterruptedException e) {
        }
        LocalTime end = LocalTime.now();
        System.out.println(Thread.currentThread() + " end " + number.get() + " @ " + end
            + ", seconds cost " + (ChronoUnit.SECONDS.between(start, end)));
    }
}

初始化了一個(gè)線程池大小為 5 的 TaskScheduler, 避免了所有任務(wù)都用一個(gè)線程來(lái)執(zhí)行。 上例中的 fixedRate 為 5 秒,任務(wù)執(zhí)行時(shí)間在 0 ~ 15 秒之間,先來(lái)看一組數(shù)據(jù)(樣本數(shù)據(jù)越多越生動(dòng))

把 start 行用紅色顯示。

  • 任務(wù) 1 與 2 之間間隔時(shí)間是任務(wù)時(shí)長(zhǎng) 13,所以任務(wù) 2 在 1 結(jié)束后立即啟動(dòng)
  • 任務(wù) 3 與 2 之間間隔還不到 5 秒,也是在任務(wù) 2 結(jié)束后立即執(zhí)行
  • 后面都是在上次任務(wù)結(jié)束后立即執(zhí)行下一次任務(wù),看到 7 與 8 之間相差 0 秒,13 與 14 之間相關(guān) 2 秒

從上面的結(jié)果分析,似乎 fixedRate 越到后面都不起作用,總是任務(wù)一個(gè)接一個(gè)的執(zhí)行。也就是說(shuō)上面 fixedRate 的示意串

T1.T1WWWT2.T2.T2WW.T3.T3.T3.T3.T3.T4.T4.T4.T4.T4.T4.T4T5T5WWWT6.T6........

已經(jīng)不成立了,當(dāng)中間發(fā)生了一長(zhǎng)時(shí)間的任務(wù)后,fixedRate 變成了如下的形式

T1.T1.WWWT2.T2.T2.T2.T2.T2.T2.T2.T2.T2.T2.T2.T3.T3.T3.T3.T4.T4.T4.T5.T5.T5.......

任務(wù)間的等待都被抹除掉了,這是為什么呢?因?yàn)?fixedRate 會(huì)對(duì)將要執(zhí)行的任務(wù)作一個(gè)預(yù)先編排,由上輸出可以第一次任務(wù)在 01:23:11 時(shí)間點(diǎn)啟動(dòng),所以 fixedRate 會(huì)基于此把一個(gè)時(shí)間表準(zhǔn)備好,如下

01:23:16 T2 T1 執(zhí)行后時(shí)間來(lái)到了 01:23:24, 下一次任務(wù) T2 安排在更早的時(shí)間,所以立即執(zhí)行 T2
01:23:21 T3 T2 完后時(shí)間是 01:23:28, T3 的安排時(shí)間也比它早,所以也是立即執(zhí)行 T3
01:23:26 T4 T3 完后時(shí)間是 01:23:40, 無(wú)需等待立即執(zhí)行 T4
01:23:31 T5

后面的情況都是一樣的, T5.endTime > T6.scheduledTime + fixedRate, 所以立即執(zhí)行 T6

除非有一些短任務(wù)能把時(shí)間壓縮回去,造成上一次任務(wù)結(jié)束后需要進(jìn)行等待

01:23:35 T6
01:23:41 T7

因此,fixedRate 總是在上一次任務(wù)結(jié)束后從時(shí)間表中挑出下一次任務(wù),對(duì)比該任務(wù)所預(yù)先排好的時(shí)間是否晚于上次任務(wù)啟動(dòng)時(shí)間加上 fixedRate 值,是則等待到預(yù)定的時(shí)間,否則立即執(zhí)行。

假設(shè) T1 執(zhí)行完后時(shí)間是 T1.endTime, 這時(shí)候判斷 T1.endTime < T2.scheduledTime + fixedRate, 是則等待到 T2.scheduledTime 啟動(dòng) T2, 否則立即執(zhí)行 T2

我們可以用代碼進(jìn)一步來(lái)驗(yàn)證上面的說(shuō)法,其實(shí)最具說(shuō)服力的莫過(guò)于源代碼,這里只提供感觀體驗(yàn)

代碼的改動(dòng)是第一次任務(wù)執(zhí)行時(shí)間為 23 秒,此后的任務(wù)是不耗時(shí)的空操作

    private AtomicBoolean firstTime = new AtomicBoolean(true); 
    @Scheduled(fixedRate = 5000)
    public void job() {
        LocalTime start = LocalTime.now();
        System.out.println(Thread.currentThread() + " start " + number.incrementAndGet() + " @ "  + start);
        if (firstTime.getAndSet(false)) {
            try {
                Thread.sleep(23000);
            } catch (InterruptedException e) {
            }
        }
        LocalTime end = LocalTime.now();
        System.out.println(Thread.currentThread() + " end " + number.get() + " @ " + end
            + ", seconds cost " + (ChronoUnit.SECONDS.between(start, end)));
    }

輸出為

因?yàn)榈谝淮稳蝿?wù) 23 秒的延誤,所以后續(xù)的任務(wù) 2, 3, 4, 5 都是上次任務(wù)(耗時(shí)為 0)完后立即執(zhí)行,任務(wù) 6 把 2 秒的差距找回來(lái)了,以后都是每隔 5 秒執(zhí)行一次。

fixedDelay 的邏輯就相當(dāng)簡(jiǎn)單了,基本無(wú)需用代碼來(lái)演示。不妨把上面的代碼中的 fixedRate 改成 fixedDelay 來(lái)一見(jiàn)分曉:

Thread[taskScheduler-1,5,main] start 1 @ 02:54:33.750
Thread[taskScheduler-1,5,main] end 1 @ 02:54:43.756, seconds cost 10
Thread[taskScheduler-1,5,main] start 2 @ 02:54:48.765
Thread[taskScheduler-1,5,main] end 2 @ 02:55:00.767, seconds cost 12
Thread[taskScheduler-2,5,main] start 3 @ 02:55:05.769
Thread[taskScheduler-2,5,main] end 3 @ 02:55:11.772, seconds cost 6
Thread[taskScheduler-1,5,main] start 4 @ 02:55:16.775
Thread[taskScheduler-1,5,main] end 4 @ 02:55:21.781, seconds cost 5
Thread[taskScheduler-3,5,main] start 5 @ 02:55:26.785
Thread[taskScheduler-3,5,main] end 5 @ 02:55:27.787, seconds cost 1
Thread[taskScheduler-3,5,main] start 6 @ 02:55:32.789
Thread[taskScheduler-3,5,main] end 6 @ 02:55:41.792, seconds cost 9
Thread[taskScheduler-3,5,main] start 7 @ 02:55:46.794

總是上次任務(wù)結(jié)束 5 秒后,由此可見(jiàn) fixedDelay 不存在任務(wù)的預(yù)先編排操作了,都是相機(jī)而為。

最后小結(jié)一下:fixedRate 每次任務(wù)結(jié)束后會(huì)從任務(wù)編排表中找下一次該執(zhí)行的任務(wù),判斷是否到時(shí)機(jī)執(zhí)行。fixedRate 的任務(wù)某次執(zhí)行時(shí)間再長(zhǎng)也不會(huì)造成兩次任務(wù)實(shí)例同時(shí)執(zhí)行,除非用了 @Async 注解。 fixedDelay 總是前一次任務(wù)完成后,延時(shí)固定長(zhǎng)度然后執(zhí)行一次任務(wù)

定時(shí)任務(wù)fixedRate和fixedDelay區(qū)別最簡(jiǎn)單的解釋

看了網(wǎng)上很多文章,一大段的測(cè)試代碼,復(fù)雜的解釋,真的是覺(jué)得好多此一舉,看的人頭疼

其實(shí)很簡(jiǎn)單很簡(jiǎn)單一兩句話就能把fixedRate和fixedDelay的區(qū)別解釋的一清二楚:

  • fixedRate=5000:下一次任務(wù)的開(kāi)始時(shí)間是這一次開(kāi)始的時(shí)間+5秒
  • fixedDelay=5000:下一次任務(wù)的開(kāi)始時(shí)間是這一次開(kāi)始的時(shí)間+這一次任務(wù)的執(zhí)行耗時(shí)+5秒

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

相關(guān)文章

  • java 實(shí)現(xiàn)雙向鏈表實(shí)例詳解

    java 實(shí)現(xiàn)雙向鏈表實(shí)例詳解

    這篇文章主要介紹了java 實(shí)現(xiàn)雙向鏈表實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • java語(yǔ)言求解兔子問(wèn)題代碼分析

    java語(yǔ)言求解兔子問(wèn)題代碼分析

    這篇文章主要介紹了Java語(yǔ)言求解兔子問(wèn)題代碼分析,具有一定借鑒價(jià)值,需要的朋友可以了解下。
    2017-12-12
  • Springboot工具類ReflectionUtils使用教程

    Springboot工具類ReflectionUtils使用教程

    這篇文章主要介紹了Springboot內(nèi)置的工具類之ReflectionUtils的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2022-12-12
  • Java刪除二叉搜索樹(shù)的任意元素的方法詳解

    Java刪除二叉搜索樹(shù)的任意元素的方法詳解

    這篇文章主要介紹了Java刪除二叉搜索樹(shù)的任意元素的方法,結(jié)合實(shí)例形式詳細(xì)分析了java這對(duì)二叉搜索樹(shù)的遍歷、查找、刪除等相關(guān)操作技巧與使用注意事項(xiàng),需要的朋友可以參考下
    2020-03-03
  • servlet基礎(chǔ)知識(shí)_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    servlet基礎(chǔ)知識(shí)_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要為大家詳細(xì)介紹了servlet基礎(chǔ)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • java基礎(chǔ)之標(biāo)簽、按鈕和按鈕事件簡(jiǎn)介

    java基礎(chǔ)之標(biāo)簽、按鈕和按鈕事件簡(jiǎn)介

    本文給大家?guī)?lái)的是java圖形界面的基礎(chǔ)知識(shí),簡(jiǎn)單介紹了標(biāo)簽、按鈕和按鈕事件,十分的詳細(xì),有需要的小伙伴可以參考下。
    2015-06-06
  • Java用戶交互scanner及運(yùn)算結(jié)構(gòu)代碼詳解

    Java用戶交互scanner及運(yùn)算結(jié)構(gòu)代碼詳解

    這篇文章主要介紹了Java用戶交互scanner及運(yùn)算結(jié)構(gòu)代碼詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-12-12
  • IntelliJ IDEA 安裝及初次使用圖文教程(2020.3.2社區(qū)版)

    IntelliJ IDEA 安裝及初次使用圖文教程(2020.3.2社區(qū)版)

    這篇文章主要介紹了IntelliJ IDEA 安裝及初次使用(2020.3.2社區(qū)版),本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • JVM自定義類加載器在代碼擴(kuò)展性實(shí)踐分享

    JVM自定義類加載器在代碼擴(kuò)展性實(shí)踐分享

    這篇文章主要介紹了JVM自定義類加載器在代碼擴(kuò)展性實(shí)踐分享,一個(gè)類型從被加載到虛擬機(jī)內(nèi)存中開(kāi)始,到卸載出內(nèi)存為止,它的整個(gè)生命周期將會(huì)經(jīng)歷加載、驗(yàn)證、準(zhǔn)備、解析、初始化 、使用和卸載七個(gè)階段,其中驗(yàn)證、準(zhǔn)備、解析三個(gè)部分統(tǒng)稱為連接
    2022-06-06
  • Java SpringSecurity入門(mén)案例與基本原理詳解

    Java SpringSecurity入門(mén)案例與基本原理詳解

    這篇文章主要介紹了java中Spring Security的實(shí)例詳解的相關(guān)資料,spring security是一個(gè)多方面的安全認(rèn)證框架,提供了基于JavaEE規(guī)范的完整的安全認(rèn)證解決方案,需要的朋友可以參考下
    2021-09-09

最新評(píng)論

玉山县| 曲沃县| 象山县| 闽清县| 岳池县| 武安市| 蒙阴县| 巴马| 合水县| 尼勒克县| 东乌珠穆沁旗| 襄汾县| 福清市| 南平市| 南汇区| 珲春市| 伊金霍洛旗| 楚雄市| 乌兰县| 徐闻县| 富锦市| 益阳市| 将乐县| 神木县| 乡宁县| 乐业县| 正安县| 清河县| 额济纳旗| 鄂州市| 许昌市| 乡城县| 横山县| 红河县| 新宁县| 黔西| 民勤县| 青神县| 平武县| 万安县| 盘山县|