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

Spring自帶定時(shí)任務(wù)@Scheduled注解實(shí)例講解

 更新時(shí)間:2024年06月06日 10:13:41   作者:心流時(shí)間  
這篇文章主要介紹了Spring自帶定時(shí)任務(wù)@Scheduled注解的相關(guān)知識,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

1. cron表達(dá)式生成器

cron表達(dá)式生成器:https://cron.qqe2.com/

2. 簡單定時(shí)任務(wù)代碼示例:每隔兩秒打印一次字符

import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
@Service
@EnableScheduling
public class ScheduleDemo1 {
    @Scheduled(cron = "*/2 * * * * ?")
    public static void test() {
        // 十六進(jìn)制轉(zhuǎn)換為字符
        System.out.print((char) Integer.parseInt("5fc3", 16));
        System.out.print((char) Integer.parseInt("6d41", 16));
        System.out.print((char) Integer.parseInt("65f6", 16));
        System.out.print((char) Integer.parseInt("95f4", 16));
        System.out.println();
    }
}

輸出:

3. @Scheduled注解的參數(shù)

3.1 cron

參數(shù)接收一個(gè)cron表達(dá)式,cron表達(dá)式是一個(gè)以空格為間隔符來區(qū)分不同域的字符串,總共有6個(gè)或7個(gè)域。cron表達(dá)式從左到右每個(gè)域分別標(biāo)識的[秒] [分] [小時(shí)] [日] [月] [周] [年],其中[年]不是必選的域可以省略。

序號必填值的范圍允許的通配符
10-59, - * /
20-59, - * /
3時(shí)0-23, - * /
41-31, - * ? / L W
51-12 / JAN-DEC, - * /
61-7 or SUN-SAT, - * ? / L #
71970-2099, - * /

通配符說明:

  • * 表示所有值,例如:在時(shí)的字段上設(shè)置 *,表示每一個(gè)小時(shí)都會觸發(fā)。
  •  ? 表示不指定值,即當(dāng)前使用的場景為不需要關(guān)心這個(gè)字段設(shè)置的值。例如:要在每月的10號觸發(fā)一個(gè)操作,但不關(guān)心是周幾,所以需要周位置的那個(gè)字段設(shè)置為“?”, 具體設(shè)置為 0 0 0 10 * ? 。
  •  - 表示區(qū)間,例如:在小時(shí)上設(shè)置 “10-12”,表示 10,11,12點(diǎn)都會觸發(fā)。
  •  , 表示指定多個(gè)值,例如在周字段上設(shè)置 “MON,WED,FRI” 表示周一,周三和周五觸發(fā)。
  •  / 用于遞增觸發(fā),如在秒上面設(shè)置“5/15” 表示從5秒開始,每隔15秒觸發(fā)(5,20,35,50)。在日字段上設(shè)置‘1/3’所示每月1號開始,每隔三天觸發(fā)一次
  •  L 表示最后的意思,在日字段設(shè)置上,表示當(dāng)月的最后一天(依據(jù)當(dāng)前月份,如果是二月還會依據(jù)是否是閏年), 在周字段上表示星期六,相當(dāng)于“7”或“SAT”。如果在“L”前加上數(shù)字,則表示該數(shù)據(jù)的最后一個(gè)。例如在周字段上設(shè)置“6L”這樣的格式,則表示“本月最后一個(gè)星期五”。
  •  W表示離指定日期的最近那個(gè)工作日(周一至周五)。例如在日字段上置“15W”,表示離每月15號最近的那個(gè)工作日觸發(fā)。如果15號正好是周六,則找最近的周五(14號)觸發(fā), 如果15號是周未,則找最近的下周一(16號)觸發(fā)。如果15號正好在工作日(周一至周五),則就在該天觸發(fā)。如果指定格式為 “1W”,它則表示每月1號往后最近的工作日觸發(fā)。如果1號正是周六,則將在3號下周一觸發(fā)。(注,“W”前只能設(shè)置具體的數(shù)字,不允許區(qū)間“-”)。
  •  #序號(表示每月的第幾個(gè)周幾),例如在周字段上設(shè)置“6#3”表示在每月的第三個(gè)周六。注意如果指定“#5”,正好第五周沒有周六,則不會觸發(fā)該配置;小提示:‘L’和 ‘W’可以一組合使用。如果在日字段上設(shè)置“LW”,則表示在本月的最后一個(gè)工作日觸發(fā);周字段的設(shè)置,若使用英文字母是不區(qū)分大小寫的,即MON與mon相同。

示例:

  • 每隔5秒執(zhí)行一次:*/5 * * * * ?
  • 每隔1分鐘執(zhí)行一次:0 */1 * * * ?
  • 每天23點(diǎn)執(zhí)行一次:0 0 23 * * ?
  • 每天凌晨1點(diǎn)執(zhí)行一次:0 0 1 * * ?
  • 每月1號凌晨1點(diǎn)執(zhí)行一次:0 0 1 1 * ?

3.2 fixedDelay

上一次執(zhí)行完成后延遲多久執(zhí)行下一次,以上一次任務(wù)執(zhí)行的完成時(shí)間開始延遲,如:

@Scheduled(fixedDelay = 5000) //上一次執(zhí)行完成后延遲5s再執(zhí)行

3.3 fixedRate

固定延遲多久執(zhí)行下一次任務(wù),不依賴于上一次任務(wù)執(zhí)行成功的時(shí)間,如:

@Scheduled(fixedRate= 5000) //上一次執(zhí)行后延遲5s就開始執(zhí)行

3.4 initialDelay

啟動(dòng)后延遲多久后執(zhí)行第一次,可根據(jù)場景搭配fixedRate或fixedDelay實(shí)現(xiàn)定時(shí)調(diào)度,如:

@Scheduled(initialDelay = 5000,fixedRate= 300000) //啟動(dòng)后延遲5s執(zhí)行,之后每次執(zhí)行時(shí)間間隔5min

3.5 fixedDelayString、fixedRateString、initialDelayString等是String類型,支持占位符

如:@Scheduled(fixedDelayString = “${task.fixed-delay}”)

3.6 timeUnit

時(shí)間單位,默認(rèn)毫秒

TimeUnit timeUnit() default TimeUnit.MILLISECONDS;

4. 問題:定時(shí)器的任務(wù)默認(rèn)是按照順序執(zhí)行的,可能導(dǎo)致一些任務(wù)無法執(zhí)行

我創(chuàng)建定時(shí)器執(zhí)行任務(wù)目的是為了讓它多線程執(zhí)行任務(wù),但是后來才發(fā)現(xiàn),@Scheduled注解的方法默認(rèn)是按照順序執(zhí)行的,這會導(dǎo)致當(dāng)一個(gè)任務(wù)掛死的情況下,其它任務(wù)都在等待,無法執(zhí)行。

@Scheduled注解加載的過程,以及它是如何執(zhí)行的:

4.1 ScheduledAnnotationBeanPostProcessor類處理器解析帶有@Scheduled注解的方法

4.2 processScheduled方法處理@Scheduled注解后面的參數(shù),并將其添加到任務(wù)列表中

4.3 執(zhí)行任務(wù)。

ScheduledTaskRegistrar類為Spring容器的定時(shí)任務(wù)注冊中心。Spring容器通過線程處理注冊的定時(shí)任務(wù)

首先,調(diào)用scheduleCronTask初始化定時(shí)任務(wù)。

然后,在ThreadPoolTaskScheduler類中,會對線程池進(jìn)行初始化,線程池的核心線程數(shù)量為1,

private volatile int poolSize = 1;

阻塞隊(duì)列為DelayedWorkQueue。

因此,原因就找到了,當(dāng)有多個(gè)方法使用@Scheduled注解時(shí),就會創(chuàng)建多個(gè)定時(shí)任務(wù)到任務(wù)列表中,當(dāng)其中一個(gè)任務(wù)沒執(zhí)行完時(shí),其它任務(wù)在阻塞隊(duì)列當(dāng)中等待,因此,所有的任務(wù)都是按照順序執(zhí)行的,只不過由于任務(wù)執(zhí)行的速度相當(dāng)快,讓我們感覺任務(wù)都是多線程執(zhí)行的。

下面舉例來驗(yàn)證一下,將上述的某個(gè)定時(shí)任務(wù)添加睡眠時(shí)間,觀察另一個(gè)定時(shí)任務(wù)是否輸出。

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Slf4j
@EnableScheduling
@Component
public class ScheduleDemo2 {
    private static final ThreadLocal<Integer> threadLocalA = new ThreadLocal<>();
    @Scheduled(cron = "0/2 * * * * ?")
    public void taskA() {
        try {
            log.info("執(zhí)行了ScheduleTask類中的taskA方法");
            Thread.sleep(TimeUnit.SECONDS.toMillis(10));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    @Scheduled(cron = "0/1 * * * * ?")
    public void taskB() {
        int num = threadLocalA.get() == null ? 0 : threadLocalA.get();![在這里插入圖片描述](https://img-blog.csdnimg.cn/direct/2022840e83f049e2875381196e7c55ea.png)
        log.info("taskB方法執(zhí)行次數(shù):{}", ++num);
        threadLocalA.set(num);
    }
}

輸出:可以觀察到兩個(gè)定時(shí)任務(wù)不是同時(shí)執(zhí)行的,是按順序執(zhí)行的

想要避免順序執(zhí)行,進(jìn)行并發(fā),就要配置定時(shí)任務(wù)線程池:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledThreadPoolExecutor;
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(getExecutor());
    }
    @Bean
    public Executor getExecutor(){
        return new ScheduledThreadPoolExecutor(5);
    }
}

輸出:可以觀察到兩個(gè)定時(shí)任務(wù)不是順序執(zhí)行了,從出現(xiàn)次數(shù)的亂序這種多線程問題也可以看出是并發(fā)執(zhí)行了

從輸出結(jié)果我們可以看到,即使testA休眠,但是testB仍然正常執(zhí)行,并且其還復(fù)用了其它線程,導(dǎo)致執(zhí)行次數(shù)發(fā)生了變化。

5. 問題:當(dāng)系統(tǒng)時(shí)間發(fā)生改變時(shí),@Scheduled注解失效

另外一種情況就是在配置完線程池之后,當(dāng)你手動(dòng)修改服務(wù)器時(shí)間時(shí),目前我做的測試就是服務(wù)器時(shí)間調(diào)前,則會導(dǎo)致注解失效,而服務(wù)器時(shí)間調(diào)后,則不會影響注解的作用。

原因:

JVM啟動(dòng)之后會記錄當(dāng)前系統(tǒng)時(shí)間,然后JVM根據(jù)CPU ticks自己來算時(shí)間,此時(shí)獲取的是定時(shí)任務(wù)的基準(zhǔn)時(shí)間。如果此時(shí)將系統(tǒng)時(shí)間進(jìn)行了修改,當(dāng)Spring將之前獲取的基準(zhǔn)時(shí)間與當(dāng)下獲取的系統(tǒng)時(shí)間進(jìn)行比對不一致,就會造成Spring內(nèi)部定時(shí)任務(wù)失效。因?yàn)榇藭r(shí)系統(tǒng)時(shí)間發(fā)生變化了,不會觸發(fā)定時(shí)任務(wù)。

解決辦法:

重啟項(xiàng)目

不使用@Scheduled注解,改成ScheduledThreadPoolExecutor進(jìn)行替代,部分代碼:

實(shí)際項(xiàng)目中一般使用xxl-job、Quartz等框架,@Scheduled注解會使用的話也是定時(shí)更新一些變量的值,大量的定時(shí)任務(wù)還是使用專門的定時(shí)任務(wù)框架實(shí)現(xiàn)

參考資料:

參考1
參考2
參考3

到此這篇關(guān)于Spring自帶定時(shí)任務(wù)@Scheduled注解的文章就介紹到這了,更多相關(guān)Spring定時(shí)任務(wù)@Scheduled注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot集成Swagger使用SpringSecurity控制訪問權(quán)限問題

    SpringBoot集成Swagger使用SpringSecurity控制訪問權(quán)限問題

    這篇文章主要介紹了SpringBoot集成Swagger使用SpringSecurity控制訪問權(quán)限問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • struts+spring+hibernate三個(gè)框架的整合

    struts+spring+hibernate三個(gè)框架的整合

    這篇文章主要介紹了struts+spring+hibernate三個(gè)框架的整合,需要的朋友可以參考下
    2017-09-09
  • SpringBoot超詳細(xì)講解事務(wù)管理

    SpringBoot超詳細(xì)講解事務(wù)管理

    事務(wù)的作用就是為了保證用戶的每一個(gè)操作都是可靠的,事務(wù)中的每一步操作都必須成功執(zhí)行,只要有發(fā)生異常就 回退到事務(wù)開始未進(jìn)行操作的狀態(tài)。事務(wù)管理是Spring框架中最為常用的功能之一,我們在使用Spring Boot開發(fā)應(yīng)用時(shí),大部分情況下也都需要使用事務(wù)
    2022-08-08
  • Java分頁工具類及其使用(示例分享)

    Java分頁工具類及其使用(示例分享)

    本篇文章主要分享了Java分頁工具類及其使用的示例代碼,具有一定的參考價(jià)值,下面跟著小編一起來看下吧
    2017-01-01
  • SpringCloud微服務(wù)之Hystrix組件實(shí)現(xiàn)服務(wù)熔斷的方法

    SpringCloud微服務(wù)之Hystrix組件實(shí)現(xiàn)服務(wù)熔斷的方法

    微服務(wù)架構(gòu)特點(diǎn)就是多服務(wù),多數(shù)據(jù)源,支撐系統(tǒng)應(yīng)用。這樣導(dǎo)致微服務(wù)之間存在依賴關(guān)系。這篇文章主要介紹了SpringCloud微服務(wù)之Hystrix組件實(shí)現(xiàn)服務(wù)熔斷的方法,需要的朋友可以參考下
    2019-08-08
  • 使用Java實(shí)現(xiàn)裁剪和壓縮PPT中的圖片

    使用Java實(shí)現(xiàn)裁剪和壓縮PPT中的圖片

    在工作中,PPT演示文稿廣泛應(yīng)用于報(bào)告、課程內(nèi)容展示以及項(xiàng)目計(jì)劃,然而,當(dāng)?PPT?文件中包含大量圖片時(shí),文件大小常常大幅增加,導(dǎo)致加載緩慢、分享困難等問題,因此在這篇文章中,我們將詳細(xì)介紹如何使用Java實(shí)現(xiàn)裁剪和壓縮PPT中的圖片,需要的朋友可以參考下
    2026-03-03
  • Java實(shí)現(xiàn)大文件的分片上傳與下載(springboot+vue3)

    Java實(shí)現(xiàn)大文件的分片上傳與下載(springboot+vue3)

    這篇文章主要為大家詳細(xì)介紹了java基于springboot+vue3如何大文件的分片上傳與下載,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2023-06-06
  • SpringMVC請求參數(shù)的使用總結(jié)

    SpringMVC請求參數(shù)的使用總結(jié)

    在日常使用SpringMVC進(jìn)行開發(fā)的時(shí)候,有可能遇到前端各種類型的請求參數(shù),本文主要接介紹了SpringMVC請求參數(shù)的使用總結(jié),感興趣的可以了解一下
    2021-06-06
  • Java字符串?dāng)?shù)字左右補(bǔ)全0的四種方式

    Java字符串?dāng)?shù)字左右補(bǔ)全0的四種方式

    這篇文章主要給大家介紹了關(guān)于Java字符串?dāng)?shù)字左右補(bǔ)全0的四種方式,在編程中有時(shí)候我們需要對一個(gè)字符串進(jìn)行字符填充,以滿足某些特定的要求,其中補(bǔ)全0是一種常見的需求,需要的朋友可以參考下
    2023-08-08
  • 解決Java?API不能遠(yuǎn)程訪問HBase的問題

    解決Java?API不能遠(yuǎn)程訪問HBase的問題

    這篇文章主要介紹了解決Java?API不能遠(yuǎn)程訪問HBase的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06

最新評論

松滋市| 肃南| 新宾| 凤阳县| 长武县| 伽师县| 青川县| 岐山县| 图片| 高邑县| 通辽市| 侯马市| 邯郸县| 阿图什市| 溆浦县| 绥德县| 临桂县| 洛川县| 高州市| 山阳县| 东方市| 旬阳县| 广昌县| 沈阳市| 夹江县| 海伦市| 嵩明县| 大石桥市| 岚皋县| 漳州市| 乌兰县| 琼结县| 青阳县| 马尔康县| 长丰县| 峨眉山市| 卢湾区| 陆川县| 夏河县| 双辽市| 如东县|