SpringBoot 中的 @Schedule

Mr_Yan發表於2019-06-26

1.使用Schedule功能

只需要在SpringBoot的*Application.java檔案上加入@EnableScheduling註解即可使用Schedule功能

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

2.建立Service

建立com.example.schedule.service包,然後建立TaskService介面類

package com.example.schedule.service;

public interface TaskService {

    void sayHello(String type);
}

建立service介面實現包com.example.schedule.service.impl,然後建立TaskService的實現類TaskServiceImpl

package com.example.schedule.service.impl;

import com.example.schedule.service.TaskService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service
public class TaskServiceImpl implements TaskService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
  public void sayHello(String type) {
        try {
            long startTime = System.currentTimeMillis() / 1000;
            logger.info(type + " => " + startTime + " - 任務開始");

            logger.info(type + " => " + "任務執行中");

            Thread.sleep(500);

            long endTime = System.currentTimeMillis() / 1000;
            logger.info(type + " => " + endTime + " - 任務結束");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3.進入主題

建立任務包com.example.schedule.job,然後在包內建立主要的定時任務實現類ScheduleJob

package com.example.schedule.job;

import com.example.schedule.service.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduleJob {

    @Autowired
  private TaskService taskService;

  ....定時任務實現
}

使用@Scheduled定時任務,需要遵守的規則是:

  • 該方法的返回值應該是void
  • 該方法的引數應該為空

    3.1.使用fixedDelay定時任務

    @Scheduled(fixedDelay = 2000)
    public void fixedRateTask() {
    taskService.sayHello("fixedDelay");
    }

    使用fixedDelay實現定時任務時,“上次任務的結束”和“下次任務的開始”之間會持續固定的2000毫秒即2秒。任務總是會等到上一次任務結束後,等待兩秒才開始執行。

SpringBoot中的@Schedule

除了使用fixedDelay之外還可以使用fixedDelayString實現上述相同功能。

@Scheduled(fixedDelayString = "2000")
public void fixedDelayStringTask() {
    taskService.sayHello("fixedDelayString");
}

SpringBoot中的@Schedule

3.2.使用fixedRate定時任務

@Scheduled(fixedRate = 2000)
public void fixedRateTask() {
    taskService.sayHello("fixedRate");
}

使用fixedRate實現定時任務時,“上次任務的開始”和“下次任務的開始”之間會持續固定的2000毫秒即2秒。任務的開始不會等待上次任務的結束,而是在任務開始後的2秒就開始下一次任務。

SpringBoot中的@Schedule

同fixedDelay一樣fixedRate也可以使用fixedRateString方式實現。

@Scheduled(fixedRateString = "2000")
public void fixedRateStringTask() {
    taskService.sayHello("fixedRateString");
}

SpringBoot中的@Schedule

3.3.配合使用initialDelay

@Scheduled(initialDelay = 1000, fixedDelay = 2000)
public void fixedDelayWithInitialDelayTask() {
    taskService.sayHello("fixedDelayWithInitialDelayTask");
}

當定時任務設定了initialDelay時,任務在載入到時不會立即執行,會在等待initialDelay值之後開始第一次執行,隨後它將會繼續根據fixedDelay定時執行。

當然也可以將fixedDelay替換為fixedRate,同樣會在等待initialDelay值之後開始第一次執行,雖有它將會繼續根據 fixedRate定時執行。但是不可同時設定fixedDelay和fixedRate,這樣會報出org.springframework.beans.factory.BeanCreationException錯誤。

3.4.使用cron定時任務

相比fixedDelay和fixedRate的固定執行方式,cron表示式的方式可以更靈活控制任務的執行。

@Scheduled(cron = "*/5 * * * * *")
public void cronTask() {
    taskService.sayHello("cron");
}

該栗子等效於@Scheduled(fixedDelay = 5000)即上次任務執行結束後等待5秒再執行。

cron表示式,有專門的語法,這裡列舉通常使用的語法以供參考,複雜的語法請使用corn表示式生成器生成,或者學習corn語法。

cron一共有7位,但是最後一位是年,可以留空,所以我們可以寫6位:

● 第一位,表示秒,取值0-59
● 第二位,表示分,取值0-59
● 第三位,表示小時,取值0-23
● 第四位,日期天/日,取值1-31
● 第五位,日期月份,取值1-12
● 第六位,星期,取值1-7,星期一,星期二...,注:不是第1周,第二週的意思 另外:1表示星期天,2表示星期一。
● 第七位,年份,可以留空,取值1970-2099

cron中,還有一些特殊的符號,含義如下:

● (*)星號:可以理解為每的意思,每秒,每分,每天,每月,每年...

● (?)問號:問號只能出現在日期和星期這兩個位置,表示這個位置的值不確定,每天3點執行,所以第六位星期的位置,我們是不需要關注的,就是不確定的值。同時:日期和星期是兩個相互排斥的元素,通過問號來表明不指定值。比如,1月10日,比如是星期1,如果在星期的位置是另指定星期二,就前後衝突矛盾了。

● (-)減號:表達一個範圍,如在小時欄位中使用“10-12”,則表示從10到12點,即10,11,12

● (,)逗號:表達一個列表值,如在星期欄位中使用“1,2,4”,則表示星期一,星期二,星期四

● (/)斜槓:如:x/y,x是開始值,y是步長,比如在第一位(秒) 0/15就是,從0秒開始,每15秒,最後就是0,15,30,45,60 另:*/y,等同於0/y

下面列舉幾個例子供大家來驗證:

  • 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 每個月的第三個星期,星期天 執行,#號只能出現在星期的位置

4.總結

  • fixedDelay屬性確保任務結束時間和下次任務開始時間之間存在固定的時間間隔。
  • fixedRate屬性則是每隔n毫秒執行一次任務。
    當需要確保只有一個任務例項執行是,使用fixedDelay屬性;當執行的任務都是獨立的時候,使用fixedRate屬性。

相關文章