天天看點

SpringBoot | 第二十二章:定時任務的使用

前言

上兩章節,我們簡單的講解了關于異步調用和異步請求相關知識點。這一章節,我們來講講開發過程也是經常會碰見的定時任務。比如每天定時清理無效資料、定時發送短信、定時發送郵件、支付系統中的定時對賬等等,往往都會定義一些定時器,進行此業務的開發。是以,本章節介紹下在

SpringBoot

中定時任務如何使用及一點分布式定時服務的思考總結。
  • 一點知識
  • 基于JDK方式實作簡單定時
    • Timer
    • ScheduledExecutorService
  • 基于SpingTask實作定時任務
    • Cron表達式詳解
    • 自定義線程池
    • 動态添加定時任務
      • ThreadPoolTaskScheduler
      • SchedulingConfigurer
  • 基于Quartz實作定時排程
  • 分布式排程服務淺談
  • 參考資料
  • 總結
  • 最後
  • 老生常談

一點知識

JAVA

開發領域,目前可以通過以下幾種方式進行定時任務:

- Timer:jdk中自帶的一個定時排程類,可以簡單的實作按某一頻度進行任務執行。提供的功能比較單一,無法實作複雜的排程任務。

- ScheduledExecutorService:也是jdk自帶的一個基于線程池設計的定時任務類。其每個排程任務都會配置設定到線程池中的一個線程執行,是以其任務是并發執行的,互不影響。

- Spring Task:

Spring

提供的一個任務排程工具,支援注解和配置檔案形式,支援

Cron

表達式,使用簡單但功能強大。

- Quartz:一款功能強大的任務排程器,可以實作較為複雜的排程功能,如每月一号執行、每天淩晨執行、每周五執行等等,還支援分布式排程,就是配置稍顯複雜。

題外話:對于

Quartz

,早前用過1.6版本的,更新到2.x及以上版本後基本沒怎麼接觸了,原來還有倒騰過結合

Kettle

做了一些動态的定時抽取資料啥的還編寫過一個

Cron

表達式編輯器,現在基本忘記了。。等有機會,再次深入學習後再來單獨分享一些關于的

Quartz

心得吧。

基于JDK方式實作簡單定時

剛剛有介紹過,基于

JDK

方式一共有兩種:

Timer

ScheduledExecutorService

。接下來,就簡單講解下這兩種方式。

Timer

Timer

是jdk提供的

java.util.Timer

類。

簡單示例:

@GetMapping("/timer")
    public String doTimer() {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                log.info("Timer定時任務啟動:" + new Date());

            }
        }, ,);//延遲1秒啟動,每1秒執行一次
        return "timer";
           

啟動後,通路即可看見控制台周期性輸出資訊了:

-- ::  INFO  --- [        Timer-] c.l.l.s.c.controller.TaskController      : Timer定時任務啟動:Sat Aug  :: CST 
-- ::  INFO  --- [        Timer-] c.l.l.s.c.controller.TaskController      : Timer定時任務啟動:Sat Aug  :: CST 
-- ::  INFO  --- [        Timer-] c.l.l.s.c.controller.TaskController      : Timer定時任務啟動:Sat Aug  :: CST 
-- ::  INFO  --- [        Timer-] c.l.l.s.c.controller.TaskController      : Timer定時任務啟動:Sat Aug  :: CST 
-- ::  INFO  --- [        Timer-] c.l.l.s.c.controller.TaskController      : Timer定時任務啟動:Sat Aug  :: CST 
......
           

相關API簡單說明:

1、在特定時間執行任務,隻執行一次

public void schedule(TimerTask task,Date time)
           

2、在特定時間之後執行任務,隻執行一次

public void schedule(TimerTask task,long delay)
           

3、指定第一次執行的時間,然後按照間隔時間,重複執行

public void schedule(TimerTask task,Date firstTime,long period)
           

4、在特定延遲之後第一次執行,然後按照間隔時間,重複執行

public void schedule(TimerTask task,long delay,long period)
           

5、第一次執行之後,特定頻率執行,與3同

public void scheduleAtFixedRate(TimerTask task,Date firstTime,long period)
           

6、在delay毫秒之後第一次執行,後按照特定頻率執行

public void scheduleAtFixedRate(TimerTask task,long delay,long period)
           

參數:

- delay: 延遲執行的毫秒數,即在delay毫秒之後第一次執行

- period:重複執行的時間間隔

取消任務使用:

timer.cancel()

方法即可登出任務。

此類相對用的較少了,簡單了解下。

ScheduledExecutorService

ScheduledExecutorService

可以說是

Timer

的替代類,因為

Timer

不支援多線程,任務是串行的,而且也不捕獲異常,假設某個任務異常了,整個

Timer

就無法運作了。

簡單示例:

@GetMapping("/executor")
    public String ScheduledExecutorService() {
        //
        ScheduledExecutorService service = Executors.newScheduledThreadPool();
        service.scheduleAtFixedRate(new Runnable() {

            @Override
            public void run() {
                log.info("ScheduledExecutorService定時任務執行:" + new Date());                
            }
        }, , , TimeUnit.SECONDS);//首次延遲1秒,之後每1秒執行一次
        log.info("ScheduledExecutorService定時任務啟動:" + new Date());    
        return "ScheduledExecutorService!";        
    }
           

啟動後,可看見控制台按設定的頻率輸出:

-- ::  INFO  --- [nio--exec-] c.l.l.s.c.controller.TaskController      : ScheduledExecutorService定時任務啟動:Sat Aug  :: CST 
-- ::  INFO  --- [pool--thread-] c.l.l.s.c.controller.TaskController      : ScheduledExecutorService定時任務執行:Sat Aug  :: CST 
-- ::  INFO  --- [pool--thread-] c.l.l.s.c.controller.TaskController      : ScheduledExecutorService定時任務執行:Sat Aug  :: CST 
-- ::  INFO  --- [pool--thread-] c.l.l.s.c.controller.TaskController      : ScheduledExecutorService定時任務執行:Sat Aug  :: CST 
-- ::  INFO  --- [pool--thread-] c.l.l.s.c.controller.TaskController      : ScheduledExecutorService定時任務執行:Sat Aug  :: CST 
-- ::  INFO  --- [pool--thread-] c.l.l.s.c.controller.TaskController      : ScheduledExecutorService定時任務執行:Sat Aug  :: CST 
           

可同時設定多個任務,隻需再次設定

scheduleAtFixedRate

即可。

常用方法說明:

- ScheduleAtFixedRate:

public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit);
           

參數說明:

0. command:執行線程

1. initialDelay:初始化延時

2. period:兩次開始執行最小間隔時間

3. unit:計時機關

  • ScheduleWithFixedDelay:
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit);
           

參數說明:

0. command:執行線程

1. initialDelay:初始化延時

2. delay:前一次執行結束到下一次執行開始的間隔時間(間隔執行延遲時間)

3. unit:計時機關

其他的方法大家可自行谷歌下。

基于SpingTask實作定時任務

使用

SpringTask

SpringBoot

是很簡單的,使用

@Scheduled

注解即可輕松搞定。

0.啟動類,加入

@EnableScheduling

讓注解

@Scheduled

生效。

@SpringBootApplication
@EnableScheduling
@Slf4j
public class Chapter22Application {

    public static void main(String[] args) {
        SpringApplication.run(Chapter22Application.class, args);
        log.info("Chapter22啟動!");
    }
}
           

1.編寫一個排程類,系統啟動後自動掃描,自動執行。

@Component
@Slf4j
public class ScheduledTask {

    /**
     * 自動掃描,啟動時間點之後5秒執行一次
     */
    @Scheduled(fixedRate=)
    public void getCurrentDate() {
        log.info("Scheduled定時任務執行:" + new Date());
    }
}
           

2.啟動後,控制台可就看見每5秒一次輸出了:

-- ::  INFO  --- [pool--thread-] c.l.l.s.c.controller.ScheduledTask       : Scheduled定時任務執行:Sat Aug  :: CST 
-- ::  INFO  --- [pool--thread-] c.l.l.s.c.controller.ScheduledTask       : Scheduled定時任務執行:Sat Aug  :: CST 
-- ::  INFO  --- [pool--thread-] c.l.l.s.c.controller.ScheduledTask       : Scheduled定時任務執行:Sat Aug  :: CST 
-- ::  INFO  --- [pool--thread-] c.l.l.s.c.controller.ScheduledTask       : Scheduled定時任務執行:Sat Aug  :: CST 
-- ::  INFO  --- [pool--thread-] c.l.l.s.c.controller.ScheduledTask       : Scheduled定時任務執行:Sat Aug  :: CST 
......
           

使用都是簡單的,現在我們來看看注解

@Scheduled

的參數意思:

  1. fixedRate:定義一個按一定頻率執行的定時任務
  2. fixedDelay:定義一個按一定頻率執行的定時任務,與上面不同的是,改屬性可以配合

    initialDelay

    , 定義該任務延遲執行時間。
  3. cron:通過表達式來配置任務執行時間

Cron表達式詳解

一個

cron

表達式有至少6個(也可能7個)有空格分隔的時間元素。

依次順序如下表所示:

字段 允許值 允許的特殊字元
0~59 , - * /
0~59 , - * /
小時 0~23 , - * /
日期 1-31 , - * ? / L W C
月份 1~12或者JAN~DEC , - * /
星期 1~7或者SUN~SAT , - * ? / L C #
年(可選) 留白,1970~2099 , - * /

簡單舉例:

* 0/1 * * * * ?:每秒執行一次

* 0 0 2 1 * ? : 表示在每月的1日的淩晨2點調整任務

* 0 0 10,14,16 ? :每天上午10點,下午2點,4點

* 0 0 12 * * ? : 每天中午12點觸發

* 0 15 10 ? * MON-FRI : 周一至周五的上午10:15觸發

更多表達式,可通路:http://cron.qqe2.com/ 進行線上表達式編寫。簡單明了。

SpringBoot | 第二十二章:定時任務的使用

自定義線程池

從控制台輸出可以看見,多任務使用的是同一個線程。可結合上章節的異步調用來實作不同任務使用不同的線程進行任務執行。

0.編寫配置類,同時啟用

@Async

注解:

@Configuration
@EnableAsync
public class Config {
    /**
     * 配置線程池
     * @return
     */
    @Bean(name = "scheduledPoolTaskExecutor")
    public ThreadPoolTaskExecutor getAsyncThreadPoolTaskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize();
        taskExecutor.setMaxPoolSize();
        taskExecutor.setQueueCapacity();
        taskExecutor.setKeepAliveSeconds();
        taskExecutor.setThreadNamePrefix("oKong-Scheduled-");
        // 線程池對拒絕任務(無線程可用)的處理政策,目前隻支援AbortPolicy、CallerRunsPolicy;預設為後者
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //排程器shutdown被調用時等待目前被排程的任務完成
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        //等待時長
        taskExecutor.setAwaitTerminationSeconds();
        taskExecutor.initialize();
        return taskExecutor;
    }
}
           

1.排程類上加入

@Async

@Component
@Slf4j
public class ScheduledTask {

    /**
     * 自動掃描,啟動時間點之後5秒執行一次
     */
    @Async("scheduledPoolTaskExecutor")
    @Scheduled(fixedRate=)
    public void getCurrentDate() {
        log.info("Scheduled定時任務執行:" + new Date());
    }
}
           

再次啟動程式,可看見控制台輸出,任務已經是不同線程下執行了:

-- ::  INFO  --- [ong-Scheduled-] c.l.l.s.c.controller.ScheduledTask       : Scheduled定時任務執行:Sat Aug  :: CST 
-- ::  INFO  --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s):  (http)
-- ::  INFO  --- [           main] c.l.l.s.chapter22.Chapter22Application   : Started Chapter22Application in  seconds (JVM running for )
-- ::  INFO  --- [           main] c.l.l.s.chapter22.Chapter22Application   : Chapter22啟動!
-- ::  INFO  --- [ong-Scheduled-] c.l.l.s.c.controller.ScheduledTask       : Scheduled定時任務執行:Sat Aug  :: CST 
           

動态添加定時任務

使用注解的方式,無法實作動态的修改或者添加新的定時任務的,這個使用就需要使用程式設計的方式進行任務的更新操作了。可直接使用

ThreadPoolTaskScheduler

或者

SchedulingConfigurer

接口進行自定義定時任務建立。

ThreadPoolTaskScheduler

ThreadPoolTaskScheduler

SpringTask

的核心實作類,該類提供了大量的重載方法進行任務排程。這裡簡單示例下,具體的大家自行搜尋下,用的少不太了解呀。

0.建立一個

ThreadPoolTaskScheduler

類。

@Bean("taskExecutor")
    public TaskScheduler taskExecutor() {
        ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();
        executor.setPoolSize();
        executor.setThreadNamePrefix("oKong-taskExecutor-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //排程器shutdown被調用時等待目前被排程的任務完成
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //等待時長
        executor.setAwaitTerminationSeconds();
        return executor;
    }
           

1.編寫一個控制類,動态設定定時任務:

@Autowired
    TaskScheduler taskScheduler;

    @GetMapping("/poolTask")
    public String threadPoolTaskScheduler() {

        taskScheduler.schedule(new Runnable() {

            @Override
            public void run() {
                log.info("ThreadPoolTaskScheduler定時任務:" + new Date());
            }
        }, new CronTrigger("0/3 * * * * ?"));//每3秒執行一次
        return "ThreadPoolTaskScheduler!";
    }
           

2.啟動後,通路接口,即可看見控制台每3秒輸出一次:

-- ::  INFO  --- [Kong-Executor-] c.l.l.s.c.controller.TaskController      : ThreadPoolTaskScheduler定時任務:Sat Aug  :: CST 
-- ::  INFO  --- [Kong-Executor-] c.l.l.s.c.controller.TaskController      : ThreadPoolTaskScheduler定時任務:Sat Aug  :: CST 
-- ::  INFO  --- [Kong-Executor-] c.l.l.s.c.controller.TaskController      : ThreadPoolTaskScheduler定時任務:Sat Aug  :: CST 
-- ::  INFO  --- [Kong-Executor-] c.l.l.s.c.controller.TaskController      : ThreadPoolTaskScheduler定時任務:Sat Aug  :: CST 
           

SchedulingConfigurer

此類十個接口,直接實作其

configurerTasks

方法即可。

0.編寫配置類:

@Configuration
@Slf4j
public class ScheduleConfig implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setTaskScheduler(taskExecutor());
        taskRegistrar.getScheduler().schedule(new Runnable() {

            @Override
            public void run() {
                log.info("SchedulingConfigurer定時任務:" + new Date());
            }
        }, new CronTrigger("0/3 * * * * ?"));//每3秒執行一次
    }

    @Bean("taskExecutor")
    public TaskScheduler taskExecutor() {
        ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();
        executor.setPoolSize();
        executor.setThreadNamePrefix("oKong-Executor-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //排程器shutdown被調用時等待目前被排程的任務完成
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //等待時長
        executor.setAwaitTerminationSeconds();
        return executor;
    }

}
           

1.啟動後,控制台也可以看見每3秒輸出一次:

-- ::  INFO  --- [Kong-Executor-] c.l.l.s.chapter22.config.ScheduleConfig  : SchedulingConfigurer定時任務:Sat Aug  :: CST 
-- ::  INFO  --- [Kong-Executor-] c.l.l.s.chapter22.config.ScheduleConfig  : SchedulingConfigurer定時任務:Sat Aug  :: CST 
-- ::  INFO  --- [Kong-Executor-] c.l.l.s.chapter22.config.ScheduleConfig  : SchedulingConfigurer定時任務:Sat Aug  :: CST 
           

基于Quartz實作定時排程

由于本章節是基于

SpringBoot 1.x

版本的,是以沒有基于

Quartz

starter

配置,這裡直接引入了

Quartz

相關依賴包來內建。

題外話:原本使用

SpringMvc

時,一般上都是通過

xml

檔案,配置其

org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean

類進行具體執行任務的配置,指定執行的對象和方法。然後通過設定

CronTriggerFactoryBean

或者

SimpleTriggerFactoryBean

設定定時器,最後通過

org.springframework.scheduling.quartz.SchedulerFactoryBean

加入排程的

trigger

。是以,我們就使用

javaConfig

方式進行簡單內建下。

0.加入pom依賴

<!-- quartz -->
    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.2.3</version>
    </dependency>
    <!-- spring內建quartz -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
    </dependency>
    <!-- 因為SchedulerFactoryBean中依賴了org.springframework.transaction.PlatformTransactionManager,是以需依賴tx相關包,其實還是quartz有個分布式功能,是使用資料庫完成的。 -->
        <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
    </dependency>
           

1.編寫配置類。

@Configuration
@Slf4j
public class QuartzConfig {

    /**
     * 通過工廠類,建立job執行個體
     * @return
     */
    @Bean
    public MethodInvokingJobDetailFactoryBean customJobDetailFactoryBean() {

        MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
        //設定執行任務的bean
        jobDetail.setTargetBeanName("quartzTask");
        //設定具體執行的方法
        jobDetail.setTargetMethod("quartzTask");
        //同步執行,上一任務未執行完,下一任務等待
        //true 任務并發執行
        //false 下一個任務必須等待上一任務完成
        jobDetail.setConcurrent(false);
        return jobDetail; 
    }

    /**
     * 通過工廠類建立Trigger
     * @param jobDetailFactoryBean
     * @return
     * @throws ParseException 
     */
    @Bean(name = "cronTriggerBean")
    public Trigger cronTriggerBean(MethodInvokingJobDetailFactoryBean jobDetailFactoryBean) throws ParseException {
        CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
        cronTriggerFactoryBean.setJobDetail(jobDetailFactoryBean.getObject());
        cronTriggerFactoryBean.setCronExpression("0/3 * * * * ?");//每3秒執行一次
        cronTriggerFactoryBean.setName("customCronTrigger");
        cronTriggerFactoryBean.afterPropertiesSet();
        return cronTriggerFactoryBean.getObject();

    }

    /**
     * 排程工廠類,自動注入Trigger
     * @return
     */
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(Trigger... triggers) {
        SchedulerFactoryBean bean = new SchedulerFactoryBean();

        //也可以直接注入 ApplicationContext,利于 getBeansOfType擷取trigger
//        Map<String,Trigger> triggerMap = appContext.getBeansOfType(Trigger.class);
//        if(triggerMap != null) {
//            List<Trigger> triggers = new ArrayList<>(triggerMap.size());
//            //
//            triggerMap.forEach((key,trigger)->{
//                triggers.add(trigger);
//            });
//            bean.setTriggers(triggers.toArray(new Trigger[triggers.size()]));
//        }
        //這裡注意 對應的trigger 不能為null 不然會異常的
        bean.setTriggers(triggers);
        return bean;
    } 

    @Component("quartzTask")
    public class QuartzTask {

        public void quartzTask() {
            log.info("Quartz定時任務:" + new Date());
        }
    }
}
           

2.啟動後,可以看見控制台以每3秒執行一次輸出:

-- ::  INFO  --- [ryBean_Worker-] c.l.l.s.chapter22.config.QuartzConfig    : Quartz定時任務:Sun Aug  :: CST 
-- ::  INFO  --- [ryBean_Worker-] c.l.l.s.chapter22.config.QuartzConfig    : Quartz定時任務:Sun Aug  :: CST 
-- ::  INFO  --- [ryBean_Worker-] c.l.l.s.chapter22.config.QuartzConfig    : Quartz定時任務:Sun Aug  :: CST 
           

關于

Quartz

的詳細用法,再次不表了。好久沒有使用過了。有機會再來詳細闡述吧。

分布式排程服務淺談

在單機模式下,定時任務是沒什麼問題的。但當我們部署了多台服務,同時又每台服務又有定時任務時,若不進行合理的控制在同一時間,隻有一個定時任務啟動執行,這時,定時執行的結果就可能存在混亂和錯誤了。

這裡簡單的說說相關的解決方案吧,一家之言,希望大家能提出自己的見解,共同進步!

  • 剝離所有定時任務到一個工程:此方案是最簡單的,在定時任務相對較小,并發任務不多時,可以使用此方案。簡單也容易維護。當定時任務牽扯的業務越來越多,越來越雜時,維護量就成本增加了,工程會越來越臃腫,此方案就不實用了。
  • 利用

    Quartz

    叢集方案:本身

    Quartz

    是支援通過資料庫實作叢集的,以下是其叢集架構圖:
SpringBoot | 第二十二章:定時任務的使用

其實作原理也相對簡單:通過資料庫實作任務的持久化,儲存定時任務的相關配置資訊,以保證下次系統啟動時,定時任務能自動啟動。同時,通過資料庫

行鎖(for update)

機制,控制一個任務隻能被一個執行個體運作,隻有擷取鎖的執行個體才能運作任務,其他的隻能等待,直到鎖被釋放。這種方式有些弊端,就是依賴了資料庫,同時也需要保證各伺服器之間的時間需要同步,不然也是會混亂的。

現在

Quartz

也有基于

Redis

的叢集方案,有興趣的可以搜尋下。

  • 分布式鎖:可通過使用

    Redis

    或者

    ZooKeeper

    實作一個分布式鎖的機制,使得隻有擷取到鎖的執行個體方能運作定時任務,避免任務重複執行。可檢視下開源的基于

    Redis

    實作的分布式鎖項目:

    redisson

    。github位址:https://github.com/redisson/redisson有興趣的同學可以了解下。
  • 統一排程中心:

可建構一個

純粹

的定時服務,隻有

定時器

相關配置,比如

定時時間

定時排程的api接口

或者

http

服務,甚至是統一注冊中心下的服務類,如dubbo服務等。而具體的任務執行操作都在各自業務方系統中,排程中心

隻負責接口的調用

,具體實作還是在業務方。這種方案相對來說比較通用,實作起來也簡單。就是需要業務方進行約定程式設計,或者對外提供一個api接口。

當然,為了實作定時任務的自動發現和注冊功能,還是需要規範一套規則來實作自動注冊功能。簡單來說,以

Dubbo

服務為例,可以定義一個

定時任務接口類

,排程中心隻需要擷取所有實作此接口的服務,同時通過服務的相關配置(排程時間、失敗政策等)進行相關定時操作。或者編寫一個服務注冊與發現的用戶端,通過

Spring

擷取到實作此接口的所有實作類,上送到排程中心。

而且,統一排程中心,還可以對所有的定時任務的排程情況進行有效監控,日志記錄等,也可以約定接口,讓定時任務回傳定時結果,做到全局把控的目的。

以上就是對分布式排程的一點了解,有錯誤的地方還望指正,有更好的方案也希望能分享下。

參考資料

  1. https://www.cnblogs.com/yank/p/3955322.html
  2. https://blog.csdn.net/tsyj810883979/article/details/8481621
  3. https://www.cnblogs.com/javahr/p/8318728.html
  4. http://www.quartz-scheduler.org/documentation/quartz-2.1.x/quick-start.html
  5. https://spring.io/guides/gs/scheduling-tasks/

總結

本章節主要是講解了通過不同的方式實作定時任務。對于定時任務而言,本身是門大學問,一倆篇文章是講不完的。像

SpringTask

Quartz

都是很強大的排程器,兩者很相似,像如何實作任務的動态修改排程周期,動态停止相關任務,排程任務的監控,這些本文章都沒有涉及。還希望有相關需求的同學自行搜尋相關資料了。

最後

目前網際網路上很多大佬都有

SpringBoot

系列教程,如有雷同,請多多包涵了。本文是作者在電腦前一字一句敲的,每一步都是自己實踐的。若文中有所錯誤之處,還望提出,謝謝。

老生常談

  • 個人QQ:

    499452441

  • 微信公衆号:

    lqdevOps

SpringBoot | 第二十二章:定時任務的使用

個人部落格:http://blog.lqdev.cn

完整示例:chapter-22

原文位址:http://blog.lqdev.cn/2018/08/19/springboot/chapter-twenty-two/

繼續閱讀