Quartz使用教程(基础)
1.Quartz介紹
??任務(wù)調(diào)度框架“Quartz”是OpenSymphony開源組織在Job scheduling領(lǐng)域又一個開源項(xiàng)目,是完全由java開發(fā)的一個開源的任務(wù)日程管理系統(tǒng),
? ?“任務(wù)進(jìn)度管理器”就是一個在預(yù)先確定(被納入日程)的時間到達(dá)時,負(fù)責(zé)執(zhí)行(或者通知)其他軟件組件的系統(tǒng)。
簡單的來說:在某一個有規(guī)律的時間點(diǎn)干某件事。并且時間的觸發(fā)的條件可以非常復(fù)雜(比如每月最后一個工作日的17:50),復(fù)雜到需要一個專門的框架來干這個事。 Quartz就是來干這樣的事,你給它一個觸發(fā)條件的定義,它負(fù)責(zé)到了時間點(diǎn),觸發(fā)相應(yīng)的Job起來干活。
2.Quartz的觸發(fā)器
?觸發(fā)器用來告訴調(diào)度程序作業(yè)什么時候觸發(fā)。框架提供了5種觸發(fā)器類型,但兩個最常用的SimpleTrigger和CronTrigger。
? 五種類型的Trigger(定時器)
? ?SimpleTrigger,CronTirgger,DateIntervalTrigger,NthIncludedDayTrigger和Calendar類( org.quartz.Calendar)。
? ?使用場景:
? ?SimpleTrigger:執(zhí)行N次,重復(fù)N次
? ?CronTrigger:幾秒 幾分 幾時 哪日 哪月 哪周 哪年,執(zhí)行
?
3. 存儲方式
RAMJobStore(內(nèi)存作業(yè)存儲類型)和JDBCJobStore(數(shù)據(jù)庫作業(yè)存儲類型),兩種方式對比如下:
??
| ? | 優(yōu)點(diǎn)? ? | 缺點(diǎn) |
| RAMJobStore | 要外部數(shù)據(jù)庫,配置容易,運(yùn)行速度快 | 因?yàn)檎{(diào)度程序信息是存儲在被分配給JVM的內(nèi)存里面,所以,當(dāng)應(yīng)用程序停止運(yùn)行時,所有調(diào)度信息將被丟失。 另外因?yàn)榇鎯Φ絁VM內(nèi)存里面,所以可以存儲多少個Job和Trigger將會受到限制 |
| JDBCJobStor? | 支持集群,因?yàn)樗械娜蝿?wù)信息都會保存到數(shù)據(jù)庫中,可以控制事物,還有就是如果應(yīng)用服務(wù)器關(guān)閉或者重啟,任務(wù)信息都不會丟失,并且可以恢復(fù)因服務(wù)器關(guān)閉或者重啟而導(dǎo)致執(zhí)行失敗的任務(wù)? ? | 運(yùn)行速度的快慢取決與連接數(shù)據(jù)庫的快慢 |
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ?? ? ?
圖解quartz工作流程:? ? ??
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ?
? ? ? ? ?
quartz相關(guān)表達(dá)式cron:
Cron表達(dá)式是一個字符串,字符串以5或6個空格隔開,分為6或7個域,每一個域代表一個含義,Cron有如下兩種語法格式:
(1)?Seconds Minutes Hours DayofMonth Month DayofWeek Year
(2)Seconds Minutes Hours DayofMonth Month DayofWeek
corn從左到右(用空格隔開):秒 分 小時 月份中的日期 月份 星期中的日期 年份
各字段的含義:
| 字段 | 允許值 | 允許的特殊字符 |
| 秒(Seconds) | 0~59的整數(shù) | , - * / ? ?四個字符 |
| 分(Minutes) | 0~59的整數(shù) | , - * / ? ?四個字符 |
| 小時(Hours) | 0~23的整數(shù) | , - * / ? ?四個字符 |
| 日期(DayofMonth) | 1~31的整數(shù)(但是你需要考慮你月的天數(shù)) | ,- * ? / L W C ? ? 八個字符 |
| 月份(Month) | 1~12的整數(shù)或者 JAN-DEC | , - * / ? ?四個字符 |
| 星期(DayofWeek) | 1~7的整數(shù)或者 SUN-SAT (1=SUN) | ,- * ? / L W C ? ? 八個字符 |
| 年(可選,留空)(Year) | 1970~2099 | , - * / ? ?四個字符 |
?
? (1)*:表示匹配該域的任意值。假如在Minutes域使用*, 即表示每分鐘都會觸發(fā)事件。
(2)?:只能用在DayofMonth和DayofWeek兩個域。它也匹配域的任意值,但實(shí)際不會。因?yàn)镈ayofMonth和DayofWeek會相互影響。例如想在每月的20日觸發(fā)調(diào)度,不管20日到底是星期幾,則只能使用如下寫法: 13 13 15 20 * ?, 其中最后一位只能用?,而不能使用*,如果使用*表示不管星期幾都會觸發(fā),實(shí)際上并不是這樣。
(3)-:表示范圍。例如在Minutes域使用5-20,表示從5分到20分鐘每分鐘觸發(fā)一次?
(4)/:表示起始時間開始觸發(fā),然后每隔固定時間觸發(fā)一次。例如在Minutes域使用5/20,則意味著5分鐘觸發(fā)一次,而? ? ? ? ? ? ? ?25,45等分別觸發(fā)一次.?
(5),:表示列出枚舉值。例如:在Minutes域使用5,20,則意味著在5和20分每分鐘觸發(fā)一次。?
(6)L:表示最后,只能出現(xiàn)在DayofWeek和DayofMonth域。如果在DayofWeek域使用5L,意味著在最后的一個星期四觸? ? ? ? ? ?發(fā)。?
(7)W:表示有效工作日(周一到周五),只能出現(xiàn)在DayofMonth域,系統(tǒng)將在離指定日期的最近的有效工作日觸發(fā)事件。例? ? ? ? ? ? ? 如:在 DayofMonth使用5W,如果5日是星期六,則將在最近的工作日:星期五,即4日觸發(fā)。如果5日是星期天,則在 在6日(周一)觸發(fā);如果5日在星期一到星期五中的一天,則就在5日觸發(fā)。另外一點(diǎn),W的最近尋找不會跨過月份 。
(8)LW:這兩個字符可以連用,表示在某個月最后一個工作日,即最后一個星期五。?
(9)#:用于確定每個月第幾個星期幾,只能出現(xiàn)在DayofMonth域。例如在4#2,表示某月的第二個星期三。
在線生成表達(dá)式網(wǎng)址:http://cron.qqe2.com/
4.代碼演示(包含簡單調(diào)度器以及表達(dá)式觸發(fā)器兩類)
<dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.2.1</version></dependency><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz-jobs</artifactId><version>2.2.1</version></dependency>具體作業(yè)類代碼:
package com.javaxl.quartz01.job;import org.quartz.*;/*** @author 小李飛刀* @site www.javaxl.com* @company* @create 2019-02-19 11:48*/ public class RamJob implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {System.out.println("定時任務(wù)執(zhí)行......");JobDetail jobDetail = jobExecutionContext.getJobDetail();JobDataMap jobDataMap = jobDetail.getJobDataMap();System.out.println("定時任務(wù)參數(shù):name->"+jobDataMap.get("name")+",job->"+jobDataMap.get("job")+",level->"+jobDataMap.get("level"));} }執(zhí)行作業(yè)類邏輯:
public static void main(String[] args) throws SchedulerException { // 創(chuàng)建調(diào)度工廠類實(shí)例StdSchedulerFactorySchedulerFactory sc=new StdSchedulerFactory(); // 創(chuàng)建調(diào)度器實(shí)例SchedulerScheduler scheduler=sc.getScheduler(); // 創(chuàng)建任務(wù)詳情JobDetailJobDetail jobDetail=newJob(RamJob.class).withIdentity("detail01","group01") //組成唯一標(biāo)識.withDescription("this is a jobDetail") // 向具體執(zhí)行的作業(yè)類傳值方式一.usingJobData("level","老手").build();//向具體執(zhí)行的作業(yè)類傳值方式二JobDataMap jobDataMap=jobDetail.getJobDataMap();jobDataMap.put("name","張三");jobDataMap.put("job","司機(jī)");long currentTime = System.currentTimeMillis()+6*1000L;Date time = new Date(currentTime);Trigger trigger= (Trigger) TriggerBuilder.newTrigger().withIdentity("trigger1","group01") //組成唯一標(biāo)識.startAt(time) //開始時間.withDescription("this is a trigger")簡單調(diào)度器 // .withSchedule(SimpleScheduleBuilder.simpleSchedule()每隔兩秒重復(fù)執(zhí)行3次 // .withIntervalInSeconds(2).withRepeatCount(3))// 表達(dá)式調(diào)度器(在線生成定時任務(wù)表達(dá)式:http://cron.qqe2.com/) // 每5秒執(zhí)行一次作業(yè)類邏輯代碼.withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ? ")).build();// 注入作業(yè)類以及觸發(fā)器到調(diào)度器中scheduler.scheduleJob(jobDetail,trigger); // 啟動調(diào)度器scheduler.start();}這三個類是quartz的核心類:?
- Scheduler:調(diào)度器。所有的調(diào)度都是由它控制。
- Trigger: 定義觸發(fā)的條件。例子中,它的類型是SimpleTrigger,每隔1秒中執(zhí)行一次(什么是SimpleTrigger下面會有詳述)。
- JobDetail & Job: JobDetail 定義的是任務(wù)數(shù)據(jù),而真正的執(zhí)行邏輯是在Job中,例子中是HelloQuartz。 為什么設(shè)計(jì)成JobDetail + Job,不直接使用Job?這是因?yàn)槿蝿?wù)是有可能并發(fā)執(zhí)行,如果Scheduler直接使用Job,就會存在對同一個Job實(shí)例并發(fā)訪問的問題。而JobDetail & Job 方式,sheduler每次執(zhí)行,都會根據(jù)JobDetail創(chuàng)建一個新的Job實(shí)例,這樣就可以規(guī)避并發(fā)訪問的問題。
總結(jié)
以上是生活随笔為你收集整理的Quartz使用教程(基础)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 3分钟告诉你,我们是谁!
- 下一篇: 大数据时代 命令行技术过时了吗?