SpringBoot系列之使用Spring Task實(shí)現(xiàn)定時(shí)任務(wù)
一、前言介紹
定時(shí)任務(wù)是企業(yè)開(kāi)發(fā)中很常用的,比如定時(shí)推送一些接口數(shù)據(jù),在java中實(shí)現(xiàn)定時(shí)任務(wù)的方法有Spring Task、Quartz等等框架,也有JDK自帶的ScheduledExecutorService、Timer
Quartz框架比較復(fù)雜,之前我寫(xiě)過(guò)一個(gè)入門(mén)教程,讀者可以參考學(xué)習(xí):Quartz系列之任務(wù)調(diào)度框架原理簡(jiǎn)介
Spring Task是Spring3.0以后自帶的task,可以將它看成一個(gè)輕量級(jí)的Quartz,而且使用起來(lái)比Quartz簡(jiǎn)單許多
二、Spring Task
2.1 SpringTask簡(jiǎn)介
Spring Task不是獨(dú)立的項(xiàng)目,是spring-context 模塊下提供的定時(shí)任務(wù)工具,是Spring3.0以后自帶的task,可以將它看成一個(gè)輕量級(jí)的Quartz
2.2 實(shí)驗(yàn)環(huán)境準(zhǔn)備
JDK 1.8
SpringBoot2.2.1
Maven 3.2+
開(kāi)發(fā)工具
IntelliJ IDEA
smartGit
創(chuàng)建一個(gè)SpringBoot Initialize項(xiàng)目,詳情可以參考我之前博客:SpringBoot系列之快速創(chuàng)建項(xiàng)目教程
SpringBoot項(xiàng)目引入spring-boot-starter-web既可,因?yàn)閣en場(chǎng)景啟動(dòng)器會(huì)自動(dòng)引入spring-context依賴:

pom.xml參考
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">
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.2.1.RELEASE
com.example.springboot
springboot-scheduler-task
0.0.1-SNAPSHOT
springboot-scheduler-task
Demo project for Spring Boot
1.8
org.springframework.boot
spring-boot-starter-web
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
org.springframework.boot
spring-boot-maven-plugin
2.3 Enable Scheduling
開(kāi)啟Spring Scheduling必須使用@EnableScheduling注解,可以新建一個(gè)配置類(lèi),然后加上注解
package com.example.springboot.scheduler.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
*
* TaskSchedulerConfiguration
*
*
*
* @author mazq
* 修改記錄
* 修改后版本: 修改人:修改日期: 2020/07/20 13:57 修改內(nèi)容:
*
*/
@Configuration
@EnableScheduling
public class TaskSchedulerConfiguration {
}
也可以像官網(wǎng)例子一樣,加在application類(lèi):
2.4 單線程定時(shí)任務(wù)
Spring Task使用定時(shí)任務(wù),只要加上@Scheduled注解,然后也要加到Spring容器中,使用可以加上@Service等注解就可以,Scheduled策略:cron 、fixedDelay、fixedRate 三選一
ok,下面介紹@Scheduled的4個(gè)關(guān)鍵屬性
fixedDelay
Spring官網(wǎng)找到API文檔:
意思是:在上一次調(diào)用的結(jié)束與下一次調(diào)用的開(kāi)始之間以固定的毫秒數(shù)為單位執(zhí)行帶注釋的方法。
ps:這種策略比較好理解,意思就是不管任務(wù)執(zhí)行時(shí)間,只關(guān)注時(shí)間間隔就可以,畫(huà)圖表示:
fixedRate

意思是:兩次調(diào)用之間以固定的時(shí)間段(以毫秒為單位)執(zhí)行帶注釋的方法。
這種策略先預(yù)計(jì)任務(wù)執(zhí)行時(shí)間,fixedRate參數(shù)指定,畫(huà)圖描述,如圖,fixedRate=10000(10s):
代碼例子:每個(gè)任務(wù)計(jì)劃執(zhí)行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參數(shù)是用cron表達(dá)式的意思,cron表達(dá)式含義:
Cron表達(dá)式是一個(gè)字符串,字符串以5或6個(gè)空格隔開(kāi),分為6或7個(gè)域,每一個(gè)域代表一個(gè)含義。
用表格表示Cron表達(dá)式:
| 位置 | 時(shí)間域 | 允許值 | 特殊值 |
|---|---|---|---|
| 1 | 秒 | 0-59 | ,- * / |
| 2 | 分鐘 | 0-59 | ,- * / |
| 3 | 小時(shí) | 0-23 | ,- * / |
| 4 | 日期 | 1-31 | ,- * ? / L W C |
| 5 | 月份 | 1-12 | ,- * / |
| 6 | 星期 | 1-7 | ,- * ? / L C # |
| 7 | 年份(可選) | 1-31 | ,- * / |
| 特殊字符 | 代表含義 |
|---|---|
| , | 枚舉,表達(dá)一個(gè)列表值,如在星期字段中使用“MON,WED,FRI”,則表示星期一,星期三和星期五; |
| - | 區(qū)間 ,表達(dá)一個(gè)范圍,如在小時(shí)字段中使用“10-12”,則表示從10到12點(diǎn),即10,11,12; |
| * | 任意,可用在所有字段中,表示對(duì)應(yīng)時(shí)間域的每一個(gè)時(shí)刻,例如, 在分鐘字段時(shí),表示“每分鐘”; |
| / | 步長(zhǎng),x/y表達(dá)一個(gè)等步長(zhǎng)序列,x為起始值,y為增量步長(zhǎng)值。如在分鐘字段中使用0/15,則表示為0,15,30和45秒,而5/15在分鐘字段中表示5,20,35,50,你也可以使用*/y,它等同于0/y; |
| ? | 該字符只在日期和星期字段中使用,它通常指定為“無(wú)意義的值”,相當(dāng)于點(diǎn)位符; |
| L | 該字符只在日期和星期字段中使用,代表“Last”的意思,但它在兩個(gè)字段中意思不同。L在日期字段中,表示這個(gè)月份的最后一天,如一月的31號(hào),非閏年二月的28號(hào);如果L用在星期中,則表示星期六,等同于7。但是,如果L出現(xiàn)在星期字段里,而且在前面有一個(gè)數(shù)值X,則表示“這個(gè)月的最后X天”,例如,6L表示該月的最后星期五; |
| W | 工作日,該字符只能出現(xiàn)在日期字段里,是對(duì)前導(dǎo)日期的修飾,表示離該日期最近的工作日。例如15W表示離該月15號(hào)最近的工作日,如果該月15號(hào)是星期六,則匹配14號(hào)星期五;如果15日是星期日,則匹配16號(hào)星期一;如果15號(hào)是星期二,那結(jié)果就是15號(hào)星期二。但必須注意關(guān)聯(lián)的匹配日期不能夠跨月,如你指定1W,如果1號(hào)是星期六,結(jié)果匹配的是3號(hào)星期一,而非上個(gè)月最后的那天。W字符串只能指定單一日期,而不能指定日期范圍; |
| C | 該字符只在日期和星期字段中使用,代表“Calendar”的意思。它的意思是計(jì)劃所關(guān)聯(lián)的日期,如果日期沒(méi)有被關(guān)聯(lián),則相當(dāng)于日歷中所有日期。例如5C在日期字段中就相當(dāng)于日歷5日以后的第一天。1C在星期字段中相當(dāng)于星期日后的第一天。 |
| # | 該字符只能在星期字段中使用,表示當(dāng)月某個(gè)工作日。如6#3表示當(dāng)月的第三個(gè)星期五(6表示星期五,#3表示當(dāng)前的第三個(gè)),而4#5表示當(dāng)月的第五個(gè)星期三,假設(shè)當(dāng)月沒(méi)有第五個(gè)星期三,忽略不觸發(fā); |
| LW | LW組合,在日期字段可以組合使用LW,它的意思是當(dāng)月的最后一個(gè)工作日; |
每隔1分鐘執(zhí)行一次:
@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 初始化延遲時(shí)間,也就是標(biāo)識(shí)第一次延遲執(zhí)行的時(shí)間,只能配合 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:當(dāng)然,不做配置也是可以的,因?yàn)镾pringBoot有做自動(dòng)配置,自己不改配置的,就全部按照SpringBoot的自動(dòng)配置(默認(rèn))
代碼例子下載:code download

騰訊、阿里、滴滴后臺(tái)面試題匯總總結(jié) — (含答案)
面試:史上最全多線程面試題 !
最新阿里內(nèi)推Java后端面試題
JVM難學(xué)?那是因?yàn)槟銢](méi)認(rèn)真看完這篇文章

關(guān)注作者微信公眾號(hào) —《JAVA爛豬皮》
了解更多java后端架構(gòu)知識(shí)以及最新面試寶典


看完本文記得給作者點(diǎn)贊+在看哦~~~大家的支持,是作者源源不斷出文的動(dòng)力
作者:smileNicky
出處:https://www.cnblogs.com/mzq123/p/13360748.html
