在項目中常常會想要這樣的功能:
在客戶把商品加入到購物車後,如果30分鐘沒支付該訂單,那麼該訂單失效,或者在這個時候提醒客戶進行支付
,這些需求的實現都來自於定時任務調度框架.
今天來學一個簡單的
任務調度框架Quartz
簡介
Quartz:
是一個
定時任務調度框架
.比如你遇到這樣的問題:
- 想在30分鐘後,查看訂單是否支付,未支付則取消訂單
- 想在每月29號,信用卡自動還款
- …
- 想定時在某個時間,去做某件事(任務)
Quartz是要做定時任務的調度,設置好觸發
時間規則
,以及相應任務(Job)
即可.
Quartz使用
導入依賴
<!-- Quartz任務調度 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
定製一個Job(任務)
實現接口Job
package per.leiyu;
import org.quartz.*;
/**
* @author 雷雨
* @date 2020/6/27 21:05
*/
/**
* 定義了一個Job任務
*/
public class MyJob01 implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("你好,我是定時任務");
//可以通過JobExecutionContext來獲取任務的標識(name)和組別(group)
JobDetail jobDetail = jobExecutionContext.getJobDetail();
JobKey key = jobDetail.getKey();
System.out.println(key.getName());//任務標識
System.out.println(key.getGroup());//任務組別
}
}
Quartz API
package per.leiyu;
/**
* @author 雷雨
* @date 2020/6/27 21:06
*/
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.util.GregorianCalendar;
/**
* Quartz API
*/
public class HelloQuartz {
public static void main(String[] args) throws SchedulerException {
//1.定義一個調度器 Scheduler
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
//2.定義一個觸發器
//觸發器中描述任務Job的觸發規則
SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).withRepeatCount(10))
.endAt(new GregorianCalendar(2020, 5, 27, 21, 25, 30).getTime())
.build();
//3,JobDetail
//注意jbo的名字和組別和觸發器的名稱和組別是隔離的,那麼就可以同名
JobDetail jobDetail = JobBuilder.newJob(MyJob01.class).withIdentity("job1", "group1").build();
//4.將JobDetail和觸發器添加到調度器中
scheduler.scheduleJob(jobDetail,trigger);
//5.啓動 調度器開始工作
scheduler.start();
}
}
測試結果
定時任務結果,爲了方便觀察在輸出中加了時間戳 |
---|
配置
可以添加Quartz的配置文件,設置Quartz的默認啓動配置
#名爲:quartz.properties ,放置在classpath下,如果沒有此配置則按默認配置啓動
# 指定調度器名稱,非實現類
org.quarz.scheduler.instanceName = DefaultQuartzScheduler
#指定線程池實現類
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
#線程池線程數量
org.quartz.threadPool.threadCount=10
#優先級,默認5
org.quartz,threadPool.threadPriority= 5
#非持久化job
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
核心類說明
- Scheduler:調度器.所有的調度都是由它控制,是Quartz的大腦,所有任務和調度都由它管理
- Job:任務,想定時執行的事情(定義業務邏輯)
- JobDetail:基於Job,進一步包裝.其中關聯一個Job,併爲Job指定更爲詳細的屬性,比如標識等
- Trigger:觸發器.可以指定給某個任務,指定任務的觸發機制
Trigger
SimpleTrigger
以一定的時間間隔(單位是毫秒)執行的任務
- 指定起始和截止時間(時間段)
- 指定時間間隔,執行次數
SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2)//每兩秒執行一次
.withRepeatCount(10))//執行次數不超過10次
.endAt(new GregorianCalendar(2020, 5, 27, 21, 30, 30).getTime())
.build();
SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2)//每兩秒執行一次
.repeatForever())//不限制執行次數,由起始截止時間和間隔決定執行次數
.endAt(new GregorianCalendar(2020, 5, 27, 21, 30, 30).getTime())
.build();
- 注意在SimpleTrigger中指定月份是0代表的是1月,1代表的是2月
CronTrigger
適合於更復雜的任務,它支持類型於Linux Cron的語法(很強大)
- 執行Cron表達式即可
示例:
CronTrigger trigger1 = TriggerBuilder.newTrigger()
.withIdentity("trigger1","group1")
.withSchedule(CronScheduleBuilder.cronSchedule("0 0/2 10-12 * * ?"))
.build();
Cron表達式組成
表達式組成"秒 分 時 日 月 星期幾 [年]",其中年是可選參數,一般不指定
- 注意日 ,月可以決定星期,因此如果日,月執行明確的話,星期用 ?表示
位置 | 時間域 | 允許值 | 特殊值 |
---|---|---|---|
1 | 秒 | 0-59 | ,-*/ |
2 | 分鐘 | 0-59 | ,-*/ |
3 | 小時 | 0-23 | ,-*/ |
4 | 日期 | 1-31 | ,-*?/LW |
5 | 月份 | 1-12 | ,-*/ |
6 | 星期 | 1-7 | ,-*?/LW |
7 | 年份(可選) | ,-*/ |
- 在CronTrigger中表示月份是1代表的是1月,2代表的是2月
- 用數字1是的是星期天,數字2表示的是星期1,星期也可以使用英文表示
Cron表達式符號
表達式中可使用的符號的含義
符號 | 語義 |
---|---|
星號(*) | 可用在所有字段中,表示對應時間域的每一個時刻,例如在分鐘字段中,表示的是"每分鐘" |
問號(?) | 該字符只在日期和星期字段中使用,它通常指定爲"不確定值" |
減號(-) | 表示一個範圍,如在小時字段中使用"10-12",則表示從10點到12點,即10,11,12 |
逗號(,) | 表示一個列表值,如在星期字段中使用"MON,WEB,FRI",則表示星期一,星期二,星期三 |
斜杆(/) | x/y表示一個等步長序列,x爲起始值,y爲增量步長值.如在分鐘字段中使用0/15,則表示的是0,15,30,45,分鐘 |
井號(#) | 該字符只用在星期字段中,"4#2"表示的是第二個星期3,"5#4"表示的是第4個星期四 |
L | 該字符只能出現在日期和星期字段中,代表的是"Last"的意思,但它在兩個字段中含義不同 |
如果L用在星期字段中,則表示星期6,等同於7 | |
L出現在星期字段中,而且在前面有一個數值x,則表示"這個月最後一個周x",例如:6L代表這個月最後一個週五 | |
L在日期字段中,表示這個月份的最後一天,如一月的31號 | |
W | 該字符只能出現在日期字段裏,是對前導日期的修飾,表示離該日期最近的工作日 |
例如15W表示離該月15號最近的工作日,如果該月15號是星期六,則匹配14號星期五,如果15號是星期日,則匹配16號星期一;如果15號是星期二,那結果就是15號星期二;但必須注意關聯的匹配日期不能跨月 | |
LW組合 | 在日期字段可以組合使用LW,它的意思是當月的最後一個工作日 |
我是雷雨,一個
普本科
的學生,主要專注於Java後端和大數據開發
如果這篇文章有幫助到你,希望你給我一個
大大的贊
如果有什麼問題,希望你能留言
和我一起研究
,學習靠自覺,分享靠自願