SpringBoot 集成 Schedule 詳解

1、如何使用 Schedule

1.1 啓動類加註解

在啓動類上添加註解 @EnableSchedulinghtml

@SpringBootApplication
@EnableScheduling
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}
複製代碼

1.2 在方法上添加註解 @Scheduled

在須要實現定時任務的方法上添加註解 @Scheduledjava

@Component
public class MySchedule {
  
  @Scheduled(cron = "0/10 * * * * *")
  public void test() throws InterruptedException {
    log.info(Thread.currentThread().getName()+"---test");
    TimeUnit.SECONDS.sleep(12);
  }
}
複製代碼

2、Schedule 三種任務調度器

Schedule 主要有三種調度方式:fixedRate、fixedDelay、cron表達式。spring

2.1 fixedRate

固定頻率任務。segmentfault

該屬性的含義是上一個調用開始後再次調用的延時(不用等待上一次調用完成),這樣就可能會存在任務重複執行的問題,因此不是建議使用,但數據量若是不大時在配置的間隔時間內能夠執行完也是可使用的。springboot

注意:當方法的執行時間超過任務調度頻率時,調度器會在當前方法執行完成後當即執行下次任務。bash

@Scheduled(fixedRate = 1000 * 10)
public void work() {
  // do your work here
  
}
複製代碼

fixedRate 的單位是毫秒,上例中 fixedRate = 1000 * 10 表示每 10 秒執行一次。ui

設第一次執行開始時時間爲 0,正常狀況下第二次執行開始時間是第 10 秒,第三次是第 20 秒……以此類推。spa

但假如任務在 10 秒內沒有完成,好比第一次花了 15秒完成任務,那第二次執行時間也是 第15 秒,會立刻執行。線程

2.2 fixedDelay

固定間隔任務。code

下一次的任務執行時間,是從方法最後一次任務執行結束時間開始計算。並以此規則開始週期性的執行任務。

@Scheduled(fixedDelay = 1000 * 10)
public void work() {
  // do your work here
  
}
複製代碼

上例每隔10秒執行一次,設第一次執行開始時時間爲 0,若是任務的執行時間是 5 秒,那下次任務的開始時間是 5 + 10 = 15 即第 15 秒。再下一次任務開始執行時間是 15 + 5 + 10 = 30 即第 30 秒,以此類推。

2.3 Cron表達式

Cron表達式由6或7個空格分隔的時間字段組成,以下圖:

* 第一位,表示秒,取值 0-59
* 第二位,表示分,取值 0-59
* 第三位,表示小時,取值 0-23
* 第四位,日期,取值 1-31
* 第五位,月份,取值 1-12
* 第六位,星期幾,取值 1-7
* 第七位,年份,能夠留空,取值 1970-2099

(*) 星號:能夠理解爲「每」的意思,每秒、沒分
(?) 問號:只能出如今日期和星期這兩個位置,表示這個位置的值不肯定
(-) 表達一個範圍,如在小時字段中使用 10-12 ,表示從10點到12點
(,) 逗號,表達一個列表值,如在星期字段中使用 1,2,4 ,則表示星期1、星期2、星期四
(/) 斜槓,如 x/y ,x是開始值,y是步長,如在第一位(秒)使用 0/15,表示從0秒開始,每15秒

官方解釋:
0 0 3 * * ?         天天 3 點執行
0 5 3 * * ?         天天 3 點 5 分執行
0 5 3 ? * *         天天 3 點 5 分執行
0 5/10 3 * * ?      天天 3 點 5 分,15 分,25 分,35 分,45 分,55 分這幾個點執行
0 10 3 ? * 1        每週星期天的 3 點10 分執行,注:1 表示星期天
0 10 3 ? * 1 #3 每月的第三個星期的星期天 執行,#號只能出如今星期的位置

注:第六位(星期幾)中的數字可能表達不太正確,可使用英文縮寫來表示,如:Sun
複製代碼

注意,當方法的執行時間超過任務調度頻率時,調度器會在下個週期執行。

下面的例子,每 10 秒執行一次,但任務執行時間是 12 秒。

設第一次執行任務開始時間是 0,那第一次任務執行完應該是第 12 秒。第二次任務本應在第 10 秒開始執行,但因爲第 10 秒時第一次任務還沒執行完,因此第二次任務會把第 10 秒這個節點跳過,等到第 20 秒再執行第二次任務。

@Scheduled(cron = "0/10 * * * * *")
public void test() throws InterruptedException {
  log.info(Thread.currentThread().getName()+"---test");
  TimeUnit.SECONDS.sleep(12);
}
複製代碼

3、配置 TaskScheduler 線程池

Spring 會默認建立一個單線程池,若是系統中有多個定時任務要執行,任務調度器就會出現時間漂移,任務執行時間將不肯定。

因此咱們自定義一個 TaskScheduler 線程池。

@Configuration
public class InitBeanConfig {

  /** * 配置 Schedule 的線程池. */
  @Bean
  public TaskScheduler taskScheduler() {
    ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
    taskScheduler.setPoolSize(10);
    taskScheduler.setThreadNamePrefix("springboot-task");
    return taskScheduler;
  }
}
複製代碼

這樣當須要同時執行多個任務,就會最多開啓 10 個線程來處理。

參考文章:

segmentfault.com/a/119000001…

www.cnblogs.com/skychenjiaj…


以上就是 SpringBoot 集成 Schedule 的所有內容,後續開發中遇到相關問題會繼續更新,歡迎關注。

相關文章
相關標籤/搜索