SpringBoot下使用定時任務的方式全揭祕

本文旨在用通俗的語言講述枯燥的知識

定時任務做爲一種系統調度工具,在一些須要有定時做業的系統中應用普遍,如每逢某個時間點統計數據、在未來某個時刻執行某些動做...定時任務在主流開發語言均提供相應的API供開發者調用,在Java中,實現定時任務有不少種方式,原生的方式實現一個完整定時任務須要由Timer、TimerTask兩個類,Timer是定時器類,用來按計劃開啓後臺線程執行指定任務,TimerTask一個抽象類,它的子類表明一個能夠被Timer計劃的任務。除此以外,還能夠用ScheduledExecutorService類或者使用第三方jar庫Quartz,其中Quartz是一個優秀的定時任務框架,發展至今已經很是成熟,以至後來其餘的定時任務框架的核心思想或底層大多源於Quartz。java

springboot做爲Java的一種開發框架,在springboot項目中實現定時任務不只可使用Java提供的原生方式,還可使用springboot提供的定時任務API,下面,小編把Java原生和springboot全部的實現定時任務的方式作一個整合。spring

文章提綱:
一、使用線程
二、使用Timer類
三、使用ScheduledExecutorService類
四、使用Quartz
五、使用spring的@Scheduled註解
六、cron表達式

1. 線程實現

利用線程能夠設定休眠時間的方式能夠實現簡單的定時任務邏輯。編程

public static void main(String[] args){
        //定時任務間隔時間
        int sleepTime=2*1000;
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    try {
                        System.out.println("Thread方式執行一次定時任務");
                        //線程休眠規定時間
                        Thread.sleep(sleepTime);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

2. Timer類

Timer類容許調度一個TimerTask任務。使用這種方式可讓你的程序按照某一個頻度執行。springboot

public static void main(String[] args){
        int sleepTime=2*1000;
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                System.out.println("Timer方式執行一次定時任務");
            }
        };
        new Timer().schedule(timerTask,1,sleepTime);
    }

3. ScheduledExecutorService類

ScheduledExecutorService,是基於線程池設計的定時任務類,每一個調度任務都會分配到線程池中的一個線程去執行,也就是說,任務是併發執行,互不影響。
所以,基於ScheduledExecutorService類的定時任務類,歸根到底也是基於線程的調度實現的。併發

public static void main(String[] args){
        int sleepTime=2*1000;
        ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
        scheduledExecutor.scheduleAtFixedRate(
                new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("ScheduledExecutorService方式執行一次定時任務");
                    }
                }
        ,1,sleepTime, TimeUnit.SECONDS);
    }

4. 整合Quartz

Quartz是一個徹底由Java編寫的開源做業調度框架,爲在 Java 應用程序中進行做業調度提供了簡單卻強大的機制,要理解它的使用方式,須要先理解它的幾個核心概念:框架

  1. Job: 表示一個工做,要執行的具體內容。此接口中只有一個方法,以下:

void execute(JobExecutionContext context)ide

  1. JobDetail: 表示一個具體的可執行的調度程序,Job 是這個可執行程調度程序所要執行的內容,另外 JobDetail 還包含了這個任務調度的方案和策略。
  2. Trigger: 表明一個調度參數的配置,何時去調。
  3. Scheduler: 表明一個調度容器,一個調度容器中能夠註冊多個 JobDetail 和Trigger。當 Trigger 與 JobDetail 組合,就能夠被 Scheduler 容器調度了。

有了這些概念以後,咱們就能夠把Quartz整合到咱們的springboot項目中了。spring-boot

  1. 引入quartz依賴
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
  1. 配置
@Configuration
public class QuartzConfig {
    @Bean
    public JobDetail quartzDetail(){
        return JobBuilder.newJob(QuartzTest.class).withIdentity("QuartzTest").storeDurably().build();
    }
    @Bean
    public SimpleTrigger quartzTrigger(){
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(10)
                .repeatForever();
        return TriggerBuilder.newTrigger().forJob(quartzDetail())
                .withIdentity("QuartzTest")
                .withSchedule(scheduleBuilder)
                .build();
    }
}
  1. 測試
public class QuartzTest extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext){
        System.out.println("quartz執行一次定時任務 ");
    }
}

5. 使用Scheduled註解

@Scheduled是spring爲定時任務而生的一個註解,查看註解的源碼:工具

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {
//cron表達式
    String cron() default "";
//接收一個java.util.TimeZone#ID。
    String zone() default "";
//上一次執行完畢時間點以後多長時間再執行
    long fixedDelay() default -1;
//支持佔位符形式的字符串類型的fixedDelay
    String fixedDelayString() default "";
//上一次開始執行時間點以後多長時間再執行
    long fixedRate() default -1;
//支持佔位符形式的字符串類型的fixedRateString
    String fixedRateString() default "";
//第一次延遲多長時間後再執行    
    long initialDelay() default -1;
//支持佔位符形式的字符串類型的initialDelay
    String initialDelayString() default "";
}

能夠看出:Scheduled註解中的參數用來設置「定時」動做,一般狀況下,比較經常使用的參數是cron(),這意味着咱們須要學會一些cron表達式相關的語法,但因爲內容較多,篇幅較長,在這裏暫不鋪開講解,咱們把cron語法相關放到文章最後,在此先講解如何用Scheduled註解來實現定時任務。測試

  1. 開啓定時任務支持
@SpringBootApplication
/**
 * 開啓定時任務支持
 */
@EnableScheduling
public class TestApplication  extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(this.getClass());
    }
}
  1. 使用
@Component
public class ScheduledTest {
    private Logger logger = LoggerFactory.getLogger(ScheduledTest.class);
    /**
     * 每15秒執行一次定時任務
     */
    @Scheduled(cron = "0/15 * * * * ? ")
    public void testCron(){
        logger.info("Scheduled 執行一次定時任務");
    }
}

6. cron表達式

cron表達式是一個字符串其語法爲:

[秒] [分] [小時] [日] [月] [周] [年]

其中[年]爲非必填項,所以一般cron表達式一般由6或7部份內容組成,內容的取值爲數字或者一些cron表達式約定的特殊字符,這些特殊字符稱爲「通配符」,每個通配符分別代指一種值。cron表達式能夠用這樣的表格來表示:

順序 取值範圍 特殊字符串範圍
0~60 , - * /
0-60 , - * /
0-23 , - * /
1-31 , - * /
1-12 / JAN-DEC , - * ? / L W
1-7 / SUN-SAT , - * ? / L #
年(可省略) 1970-2099 , - * /

其中通配符的解釋以及做用以下:

通配符 表明的值 解釋
* 全部值 如:時字段爲*,表明每小時都觸發
? 不指定值 如:周字段爲?,表明表達式不關心是周幾
- 區間 如:時字段設置2-5,表明2,3,4,5點鐘時都觸發
, 多個值 如:時字段設置2,3,5,表明2,3,5點都會觸發
/ 遞增值 如:時字段設置0/2,表明每兩個小時觸發,時字段設置 2/5,表明從2時開始每隔5小時觸發一次
L 最後值 如:日字段設置L,表明本月最後一天
W 最近工做日 如:在日字段設置13W,表明沒約13日最近的那個工做日觸發一次
# 序號 如:在周字段設置5#2,表明每個月的第二個週五
示例:
每2秒執行一次:0/5 ?
每5分鐘執行一次:0 0/5 * ?
1分、12分、45分執行一次:0 1,12,45 * ?
天天23點59分59秒執行一次:59 59 23 ?
每個月15號凌晨3點執行一次:0 0 3 15 * ?
每個月最後一天12點執行一次:0 0 12 L * ?

以爲本文對你有幫助?請分享給更多人
關注「編程無界」,提高裝逼技能

相關文章
相關標籤/搜索