SpringBoot系列之使用Spring Task實現定時任務

@[TOC](SpringBoot系列之使用Spring Task實現定時任務)

一、前言介紹

定時任務是企業開發中很常用的,比如定時推送一些接口數據,在java中實現定時任務的方法有Spring Task、Quartz等等框架,也有JDK自帶的ScheduledExecutorService、Timer

Quartz框架比較複雜,之前我寫過一個入門教程,讀者可以參考學習:Quartz系列之任務調度框架原理簡介

Spring Task是Spring3.0以後自帶的task,可以將它看成一個輕量級的Quartz,而且使用起來比Quartz簡單許多

二、Spring Task

2.1 SpringTask簡介

Spring Task不是獨立的項目,是spring-context 模塊下提供的定時任務工具,是Spring3.0以後自帶的task,可以將它看成一個輕量級的Quartz

2.2 實驗環境準備

  • JDK 1.8
  • SpringBoot2.2.1
  • Maven 3.2+
  • 開發工具
    • IntelliJ IDEA
    • smartGit

創建一個SpringBoot Initialize項目,詳情可以參考我之前博客:SpringBoot系列之快速創建項目教程

SpringBoot項目引入spring-boot-starter-web既可,因爲wen場景啓動器會自動引入spring-context依賴:



pom.xml參考

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example.springboot</groupId>
    <artifactId>springboot-scheduler-task</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-scheduler-task</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.3 Enable Scheduling

開啓Spring Scheduling必須使用@EnableScheduling註解,可以新建一個配置類,然後加上註解

package com.example.springboot.scheduler.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
 * <pre>
 *      TaskSchedulerConfiguration
 * </pre>
 *
 * <pre>
 * @author mazq
 * 修改記錄
 *    修改後版本:     修改人:  修改日期: 2020/07/20 13:57  修改內容:
 * </pre>
 */
@Configuration
@EnableScheduling
public class TaskSchedulerConfiguration {

}

也可以像官網例子一樣,加在application類:


2.4 單線程定時任務

Spring Task使用定時任務,只要加上@Scheduled註解,然後也要加到Spring容器中,使用可以加上@Service等註解就可以,Scheduled策略:cron 、fixedDelay、fixedRate 三選一

ok,下面介紹@Scheduled的4個關鍵屬性

意思是:在上一次調用的結束與下一次調用的開始之間以固定的毫秒數爲單位執行帶註釋的方法。

ps:這種策略比較好理解,意思就是不管任務執行時間,只關注時間間隔就可以,畫圖表示:


  • fixedRate

意思是: 兩次調用之間以固定的時間段(以毫秒爲單位)執行帶註釋的方法。

這種策略先預計任務執行時間,fixedRate參數指定,畫圖描述,如圖,fixedRate=10000(10s):



代碼例子:每個任務計劃執行5s

@Scheduled( fixedRate = 5000)
    public void testFixedRate() {
        log.info("fixedRate test,thread name:[{}],execute time:[{}]",Thread.currentThread().getName(),
                LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    }
  • cron
    cron參數是用cron表達式的意思,cron表達式含義:

Cron表達式是一個字符串,字符串以5或6個空格隔開,分爲6或7個域,每一個域代表一個含義。

用表格表示Cron表達式:

位置 時間域 允許值 特殊值
1 0-59 ,- * /
2 分鐘 0-59 ,- * /
3 小時 0-23 ,- * /
4 日期 1-31 ,- * ? / L W C
5 月份 1-12 ,- * /
6 星期 1-7 ,- * ? / L C #
7 年份(可選) 1-31 ,- * /
特殊字符 代表含義
, 枚舉,表達一個列表值,如在星期字段中使用“MON,WED,FRI”,則表示星期一,星期三和星期五;
- 區間 ,表達一個範圍,如在小時字段中使用“10-12”,則表示從10到12點,即10,11,12;
* 任意,可用在所有字段中,表示對應時間域的每一個時刻,例如, 在分鐘字段時,表示“每分鐘”;
/ 步長,x/y表達一個等步長序列,x爲起始值,y爲增量步長值。如在分鐘字段中使用0/15,則表示爲0,15,30和45秒,而5/15在分鐘字段中表示5,20,35,50,你也可以使用*/y,它等同於0/y;
? 該字符只在日期和星期字段中使用,它通常指定爲“無意義的值”,相當於點位符;
L 該字符只在日期和星期字段中使用,代表“Last”的意思,但它在兩個字段中意思不同。L在日期字段中,表示這個月份的最後一天,如一月的31號,非閏年二月的28號;如果L用在星期中,則表示星期六,等同於7。但是,如果L出現在星期字段裏,而且在前面有一個數值X,則表示“這個月的最後X天”,例如,6L表示該月的最後星期五;
W 工作日,該字符只能出現在日期字段裏,是對前導日期的修飾,表示離該日期最近的工作日。例如15W表示離該月15號最近的工作日,如果該月15號是星期六,則匹配14號星期五;如果15日是星期日,則匹配16號星期一;如果15號是星期二,那結果就是15號星期二。但必須注意關聯的匹配日期不能夠跨月,如你指定1W,如果1號是星期六,結果匹配的是3號星期一,而非上個月最後的那天。W字符串只能指定單一日期,而不能指定日期範圍;
C 該字符只在日期和星期字段中使用,代表“Calendar”的意思。它的意思是計劃所關聯的日期,如果日期沒有被關聯,則相當於日曆中所有日期。例如5C在日期字段中就相當於日曆5日以後的第一天。1C在星期字段中相當於星期日後的第一天。
# 該字符只能在星期字段中使用,表示當月某個工作日。如6#3表示當月的第三個星期五(6表示星期五,#3表示當前的第三個),而4#5表示當月的第五個星期三,假設當月沒有第五個星期三,忽略不觸發;
LW LW組合,在日期字段可以組合使用LW,它的意思是當月的最後一個工作日;

每隔1分鐘執行一次:

@Scheduled(cron = "0 0/1 * * * ? ")
    public void testCron(){
        log.info("cron test,thread name:[{}],execute time:[{}]",Thread.currentThread().getName(),
                LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    
  • initialDelay
    initialDelay 初始化延遲時間,也就是標識第一次延遲執行的時間,只能配合 fixedDelay 或 fixedRate 使用
@Scheduled(initialDelay = 5000, fixedRate = 5000)
    public void testFixedRate() {
        log.info("fixedRate test,thread name:[{}],execute time:[{}]",Thread.currentThread().getName(),
                LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    }

2.5 線程池的使用配置

配置文件加上代碼,配置線程池

@Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        threadPoolTaskScheduler.setPoolSize(5);
        threadPoolTaskScheduler.setThreadNamePrefix("ThreadPoolTaskScheduler");
        threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);
        threadPoolTaskScheduler.setAwaitTerminationSeconds(60);
        return threadPoolTaskScheduler;
    }

也可以在application配置文件,加上:



ps:當然,不做配置也是可以的,因爲SpringBoot有做自動配置,自己不改配置的,就全部按照SpringBoot的自動配置(默認)

代碼例子下載:code download

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章