欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring實現(xiàn)定時任務(wù)的兩種方法詳解

 更新時間:2024年12月15日 11:17:12   作者:JWASX  
Spring提供了兩種方式實現(xiàn)定時任務(wù),一種是注解,還有一種就是接口了,這篇文章主要為大家介紹了這兩種方法的具體實現(xiàn)方法,需要的可以參考下

1. 概要

時間輪的文章在上幾篇文章中就已經(jīng)介紹完了,那么 Java 中 Spring 的定時任務(wù)肯定也是跑不掉的,那首先要學 Spring 里面定時任務(wù)的邏輯,就得先學會用法。關(guān)于 Spring,其實提供了兩種方式實現(xiàn)定時任務(wù),一種是注解,還有一種就是接口了,下面我就會講一下這兩種方式的用法,在下一篇文章中我們會繼續(xù)深入 Spring 源碼,去講解 Spring 里面的定時任務(wù)到底是怎么實現(xiàn)的。

2. 接口方式動態(tài)配置

2.1 抽象類

通過接口的方式可以實現(xiàn)時間的動態(tài)配置,先看下抽象類:

@Slf4j
@Configuration
@EnableScheduling
public abstract class ScheduledConfig implements SchedulingConfigurer {

    //定時任務(wù)周期表達式
    private String cron;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        //設(shè)置線程池,可開啟多線程
        taskRegistrar.setScheduler(taskExecutor());
        taskRegistrar.addTriggerTask(
                // 執(zhí)行定時任務(wù)
                () -> {
                    taskService();
                },
                triggerContext -> {
                    // 這里就是動態(tài)獲取任務(wù)隊列的邏輯
                    cron = getCron();
                    if(cron == null){
                        throw new RuntimeException("cron not exist");
                    }
                    // 重新獲取cron表達式
                    CronTrigger trigger = new CronTrigger(cron);
                    return trigger.nextExecutionTime(triggerContext);
                }
        );
    }

    private Executor taskExecutor() {
         return BeanUtils.getBean(ThreadPoolTaskScheduler.class);
    }



    /**
     * @Description: 執(zhí)行定時任務(wù)
     * @param:
     * @return: void
     * @Author:
     * @Date: 2020/8/28
     */
    public abstract void taskService();

    /**
     * @Description: 獲取定時任務(wù)周期表達式
     * @param:
     * @return: java.lang.String
     * @Author:
     * @Date: 2020/8/28
     */
    public abstract String getCron();

    /**
     * 判斷某任務(wù)是否開啟
     * @return
     */
    public abstract int getOpen();

    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler(){
        ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();
        executor.setPoolSize(16);
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setAwaitTerminationSeconds(60);
        return executor;
    }

}

實現(xiàn) SchedulingConfigurer 接口之后重寫 configureTasks 方法,可以設(shè)置任務(wù)的具體調(diào)度邏輯,也就是 taskRegistrar.addTriggerTask。那么里面的具體邏輯是什么呢?

// 執(zhí)行定時任務(wù)
() -> {
    taskService();
},
triggerContext -> {
    // 這里就是動態(tài)獲取任務(wù)隊列的邏輯
    cron = getCron();
    if(cron == null){
        throw new RuntimeException("cron not exist");
    }
    // 重新獲取cron表達式
    CronTrigger trigger = new CronTrigger(cron);
    return trigger.nextExecutionTime(triggerContext);
}

定時任務(wù)里面執(zhí)行具體的任務(wù),同時重寫觸發(fā)器的 nextExecutionTime 方法,在里面重新獲取 cron 表達式然后更新下一次的執(zhí)行時間。

同時最后設(shè)置了執(zhí)行任務(wù)的線程池,這樣定時任務(wù)執(zhí)行的邏輯就會交給線程池去執(zhí)行,不需要阻塞當前的工作線程。

2.2 具體實現(xiàn)類

@Component
public class ScheduledJob extends ScheduledConfig {

    String cron = "0/1 * * * * ?";
    long count = 0;

    @Override
    public void taskService() {
        int open = getOpen();
        if(open == 1){
            count++;
            PrintUtils.printLog("執(zhí)行任務(wù)!!!, 當前表達式:%s", cron);
        }
    }

    @Override
    public String getCron() {
        if(count == 5){
            cron = "0/5 * * * * ?";
        }
        return cron;
    }

    @Override
    public int getOpen() {
        return 1;
    }
}

里面的 getOpen() 就是去獲取定時任務(wù)是否開啟的,getCron() 是獲取任務(wù)執(zhí)行 cron 表達式,這兩個配置都可以寫在數(shù)據(jù)庫里面去更改。

2.3 工具類

首先是 Beanutils,從 Spring 容器中獲取對應的 bean

@Component
public class BeanUtils implements ApplicationContextAware {


    private static ApplicationContext applicationContext;


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        synchronized (BeanUtils.class){
            BeanUtils.applicationContext = applicationContext;
        }
    }



    public static <T> T getBean(String beanName) {
        synchronized (BeanUtils.class){
            if(applicationContext.containsBean(beanName)){
                return (T) applicationContext.getBean(beanName);
            }else{

                return null;
            }
        }
    }



    public static <T> Map<String, T> getBeansOfType(Class<T> baseType){
        synchronized (BeanUtils.class) {
            return applicationContext.getBeansOfType(baseType);
        }
    }

    public static <T> T getBean(Class<T> baseType){
        synchronized (BeanUtils.class) {
            return applicationContext.getBean(baseType);
        }
    }

}

然后就是打印的工具類 PrintUtils

public class PrintUtils {

    static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss:SSS");

    public static String now(){
        return LocalDateTime.now().format(FORMATTER);
    }

    public static void printLog(String str, Object...args){
        System.out.println(now() + ": " + String.format(str, args));
    }

}

2.4 執(zhí)行結(jié)果

輸出結(jié)果如上所示:可以看到在第五次輸出之后 cron 被改成了 5s 執(zhí)行一次,但是注意第 6 次距離第 5 次是 3s,可能是內(nèi)部的一些其他的處理,后面源碼再看。

3. 注解方式靜態(tài)配置

在 Spring 中,默認情況下,@Scheduled 注解標記的任務(wù)是由 Spring 內(nèi)部的一個單線程調(diào)度器(TaskScheduler)來執(zhí)行的。但是如果我們需要用自定義的線程池來執(zhí)行這些任務(wù),可以通過配置自定義的 TaskScheduler 或 ThreadPoolTaskScheduler 來實現(xiàn)。ThreadPoolTaskScheduler 里面是通過 ScheduledExecutorService 來實現(xiàn)的。

@Scheduled 注解可以實現(xiàn)定時任務(wù)、固定速率任務(wù)、固定延時任務(wù)三種,下面就一種一種來看,不過在看任務(wù)之前,先來看下一些必要的配置。

1.首先是開啟 @EnableScheduling 注解

@SpringBootApplication
@EnableScheduling
public class ScheduleApplication {

    public static void main(String[] args) {
        SpringApplication.run(ScheduleApplication.class, args);
    }

}

2.然后是配置線程池

@Configuration
public class SchedulerConfig {

    @Bean
    public ThreadPoolTaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(10); // 設(shè)置線程池大小
        scheduler.setThreadNamePrefix("MyTaskScheduler-"); // 設(shè)置線程名稱前綴
        scheduler.initialize(); // 初始化調(diào)度器
        return scheduler;
    }
}

3.1 定時任務(wù)

@Service
public class ScheduledService {

    @Scheduled(cron = "0/5 * * * * ?")
    public void runEvery15Minutes() {
        PrintUtils.printLog( "This task runs every 5 seconds");
    }
}

定時任務(wù)通過 cron 表達式來實現(xiàn),輸出結(jié)果如下:

3.2 固定延時任務(wù)

定時/延時任務(wù)-ScheduledThreadPoolExecutor的使用,固定速率和固定延時就看上面的區(qū)別就行了,因為 Spring 底層 Debug 了下默認創(chuàng)建出來的就是 ScheduledThreadPoolExecutor。不過其實核心思想都是一樣的,就算自己去實現(xiàn)了,固定速率和固定延時的核心都是一樣的,只是實現(xiàn)上會不一樣,可以對比下 ScheduledThreadPoolExecutor 和 Timer 的實現(xiàn)。Timer 的解析也在往期文章里面。定時/延時任務(wù)-Timer用法

代碼如下所示:

@Service
public class ScheduledService {

    @Scheduled(fixedDelay = 5000)
    public void runEvery15Minutes() throws InterruptedException {
        Thread.sleep(6000);
        PrintUtils.printLog("This task runs every 5 seconds, sleep 6 seconds");
    }
}

結(jié)果輸出如下,固定延時就是要確保本次任務(wù)執(zhí)行的時間距離上一次任務(wù)執(zhí)行完成的時間相差 5s

3.3 固定速率任務(wù)

@Service
public class ScheduledService {

    @Scheduled(fixedRate = 5000)
    public void runEvery15Minutes() throws InterruptedException {
        Thread.sleep(6000);
        PrintUtils.printLog("This task runs every 5 seconds, sleep 6 seconds");
    }
}

執(zhí)行結(jié)果如下:

固定速率就是確保本次任務(wù)執(zhí)行時間距離上次任務(wù)執(zhí)行的時間是期望時間 + fixedRate,如果看不懂可以去看上面那兩篇文章,很清晰。

3.4 動態(tài)配置

@Scheduled 注解使用固定的時間間隔或 cron 表達式來定義任務(wù)的執(zhí)行頻率,下面就來演示下。

  • 在 application.properties 或 application.yml 中定義動態(tài)配置
  • 在 @Scheduled 注解中引用這些字段

application.properties 配置文件如下:

# 動態(tài)配置時間間隔(單位:毫秒)
custom.fixedRate=5000

# 動態(tài)配置cron表達式
custom.cronExpression=0/5 * * * * ?
@Service
public class ScheduledService {

    @Scheduled(fixedRateString = "${custom.fixedRate}")
    public void runEvery15Minutes() throws InterruptedException {
        Thread.sleep(6000);
        PrintUtils.printLog("This task runs every 5 seconds, sleep 6 seconds");
    }
}

@Scheduled(cron = "${custom.cronExpression}")
public void runEvery15Minutes() throws InterruptedException {
    Thread.sleep(6000);
    PrintUtils.printLog("This task runs every 5 seconds, sleep 6 seconds");
}

其中一個的輸出結(jié)果如下,可以看到都是能正常調(diào)度的。

以上就是Spring實現(xiàn)定時任務(wù)的兩種方法詳解的詳細內(nèi)容,更多關(guān)于Spring定時任務(wù)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java請求Http接口OkHttp超詳細講解(附帶工具類)

    Java請求Http接口OkHttp超詳細講解(附帶工具類)

    這篇文章主要給大家介紹了關(guān)于Java請求Http接口OkHttp超詳細講解的相關(guān)資料,OkHttp是一款優(yōu)秀的HTTP客戶端框架,文中通過代碼示例介紹的非常詳細,需要的朋友可以參考下
    2024-02-02
  • Java 線程的優(yōu)先級(setPriority)案例詳解

    Java 線程的優(yōu)先級(setPriority)案例詳解

    這篇文章主要介紹了Java 線程的優(yōu)先級(setPriority)案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 零基礎(chǔ)寫Java知乎爬蟲之進階篇

    零基礎(chǔ)寫Java知乎爬蟲之進階篇

    前面幾篇文章,我們都是簡單的實現(xiàn)了java爬蟲抓取內(nèi)容的問題,那么如果遇到復雜情況,我們還能繼續(xù)那么做嗎?答案當然是否定的,之前的僅僅是入門篇,都是些基礎(chǔ)知識,給大家練手用的,本文我們就來點高大上的東西
    2014-11-11
  • 詳解Java策略模式

    詳解Java策略模式

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著Java策略模式展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • lombok注解@Data使用在繼承類上時出現(xiàn)警告的問題及解決

    lombok注解@Data使用在繼承類上時出現(xiàn)警告的問題及解決

    Lombok的@Data注解簡化了實體類代碼,但在子類中使用時會出現(xiàn)警告,指出equals和hashCode方法不會考慮父類屬性,解決方法有兩種:一是在父類上使用@EqualsAndHashCode(callSuper=true)注解;二是通過配置lombok.config文件,均能有效解決警告問題
    2024-10-10
  • SpringBoot項目打成War包部署的方法步驟

    SpringBoot項目打成War包部署的方法步驟

    這篇文章主要介紹了springboot項目如何打war包流程的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • springboot?jpa之返回表中部分字段的處理詳解

    springboot?jpa之返回表中部分字段的處理詳解

    這篇文章主要介紹了springboot?jpa之返回表中部分字段的處理詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Springboot項目中單元測試時注入bean失敗的解決方案

    Springboot項目中單元測試時注入bean失敗的解決方案

    這篇文章主要介紹了Springboot項目中單元測試時注入bean失敗的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • springboot對數(shù)據(jù)庫密碼加密的實現(xiàn)

    springboot對數(shù)據(jù)庫密碼加密的實現(xiàn)

    這篇文章主要介紹了springboot對數(shù)據(jù)庫密碼加密的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • SpringBoot文件上傳與下載功能實現(xiàn)詳解

    SpringBoot文件上傳與下載功能實現(xiàn)詳解

    文件上傳與下載是Web應用開發(fā)中常用的功能之一。接下來我們將討論如何在Spring?Boot的Web應用開發(fā)中,如何實現(xiàn)文件的上傳與下載,感興趣的可以了解一下
    2022-10-10

最新評論