目錄
一. Quartz 大致簡介
-
Quartz 是完全由 java 開發的一個開源的任務日程管理系統
任務日程管理系統 換句話說就是:
一個預先確定的日程時間到達時,負責執行任務的一個系
-
Quartz用一個.jar 庫文件,其包含了所有Quartz的核心功能,
-
這些功能有一個主要的接口: Schedule接口
它提供了簡單的操作 例如:
將任務納入日程或者從日程中取消
開始/停止/暫停日程進度
-
-
定時器的種類:
Quartz中有五中類型的Trigger:
-
SimpleTrigger : 用來觸發只需執行一次或者在給定時間觸發並且重復N次 且每次執行延遲一定時間的任務
-
CronTrigger : 按照日歷觸發,例如 每個周五 每個月的1號凌晨 2:30
-
DateIntervalTrigger
-
NthIncludedDayTrigger
-
Calendar 類(org.quartz.Calendar)
-
-
存儲方式:
Quartz自身支持 兩種存儲方式:
-
RAMJobStore (顧明思議 存放在當前內存)
-
JDBCJobStore (通過jdbc實例到數據庫)
對比:
存儲類型 優點 缺點 RAMJobStore 不需要外部數據庫,配置簡單,運行速度快 因為調度程序信息存儲在jvm 所以jvm程序停止運行時 將有丟失 且因為內存大小也有存儲個數限制 JDBCJobStore 可以存儲到數據庫中可以控制事物 因為需要連接數據庫 所以運行速度有所影響 -
-
表關系及解釋
說明 | |
qrtz_blob_triggers | Trigger作為Blob類型存儲(用於Quartz用戶用JDBC創建他們自己定制的Trigger類型,JobStore 並不知道如何存儲實例的時候) |
qrtz_calendars | 以Blob類型存儲Quartz的Calendar日歷信息, quartz可配置一個日歷來指定一個時間范圍 |
qrtz_cron_triggers | 存儲Cron Trigger,包括Cron表達式和時區信息。 |
qrtz_fired_triggers | 存儲與已觸發的Trigger相關的狀態信息,以及相聯Job的執行信息 |
qrtz_job_details | 存儲每一個已配置的Job的詳細信息 |
qrtz_locks | 存儲程序的非觀鎖的信息(假如使用了悲觀鎖) |
qrtz_paused_trigger_graps | 存儲已暫停的Trigger組的信息 |
qrtz_scheduler_state | 存儲少量的有關 Scheduler的狀態信息,和別的 Scheduler 實例(假如是用於一個集群中) |
qrtz_simple_triggers | 存儲簡單的 Trigger,包括重復次數,間隔,以及已觸的次數 |
qrtz_triggers | 存儲已配置的 Trigger的信息 |
qrzt_simprop_triggers |
-
核心類和關系
-
核心類
-
QuartzSchedulerThread:
負責執行向QuartzScheduler注冊的觸發Trigger的工作線程
-
ThreadPool :
Scheduler使用一個線程作為任務運行的基礎設施,任務通過共享線程池中的線程提高運行效率
-
QuartzSchedulerResources :
包含穿件QuartzScheduler實例所需的所有資源(JobStore,ThreadPool等)
-
JobStore :
通過類實現的接口,這些類要為org.quartz.core.QuartzScheduler的使用提供一個org.quartz.Job和org.quartz.Trigger存儲機制.作業和觸發器的存儲應該以其名稱和組的組合為唯一性
-
QuartzScheduler :
Quartz的核心,他是org.quartz.Scheduler接口的間接實現,包含調度org.quartz.Jobs ,注冊org.quartz.JobListener實例等的方法
-
Scheduler :
這是Quartz Scheduler的主要接口,代表一個獨立運行容器. 調度程序維護JobDetails和觸發器的注冊表.一旦注冊,調度程序負責執行作業,當她們的相關連的觸發器觸發(當她們的預定時間到達時 )
-
Trigger:
具有所有觸發器通用屬性的基本接口,描述了job執行的時間觸發規則,
使用TriggerBuilder實例化實際觸發器
-
JobDetail :
傳遞給定作業實例的詳細信息屬性.
JobDetails將使用JobBuilder創建/定義
-
Job :
表示要執行的"作業"的類的實現接口.
只有一個方法:
void execute(JobExecutionContext context);
(JobExecutionContext 提供調度上下文各種信息,運行時數據保存在jobDataMap中 )
Job 有個子接口StatefulJob,代表沒有狀態任務
有狀態任務不可並發,前次任務沒有執行完,后面任務則一直處於阻塞等待狀態
-
-
一個job可以被多個Trigger 綁定,但是一個Trigger只能綁定一個job!
-
-
quartz.properties Quartz可更改配置
//調度標識名 集群中每一個實例都必須使用相同的名稱 (區分特定的調度器實例) org.quartz.scheduler.instanceName:DefaultQuartzScheduler //ID設置為自動獲取 每一個必須不同 (所有調度器實例中是唯一的) org.quartz.scheduler.instanceId :AUTO //數據保存方式為持久化 org.quartz.jobStore.class :org.quartz.impl.jdbcjobstore.JobStoreTX //表的前綴 org.quartz.jobStore.tablePrefix : QRTZ_ //設置為TRUE不會出現序列化非字符串類到 BLOB 時產生的類版本問題 //org.quartz.jobStore.useProperties : true //加入集群 true 為集群 false不是集群 org.quartz.jobStore.isClustered : false //調度實例失效的檢查時間間隔 org.quartz.jobStore.clusterCheckinInterval:20000 //容許的最大作業延長時間 org.quartz.jobStore.misfireThreshold :60000 //ThreadPool 實現的類名 org.quartz.threadPool.class:org.quartz.simpl.SimpleThreadPool //線程數量 org.quartz.threadPool.threadCount : 10 //線程優先級 org.quartz.threadPool.threadPriority : 5(threadPriority 屬性的最大值是常量 java.lang.Thread.MAX_PRIORITY,等於10。最小值為常量 java.lang.Thread.MIN_PRIORITY,為1) //自創建父線程 //org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true //數據庫別名 org.quartz.jobStore.dataSource : qzDS //設置數據源 org.quartz.dataSource.qzDS.driver:com.mysql.jdbc.Driver org.quartz.dataSource.qzDS.URL:jdbc:mysql://localhost:3306/quartz org.quartz.dataSource.qzDS.user:root org.quartz.dataSource.qzDS.password:123456 org.quartz.dataSource.qzDS.maxConnection:10
-
JDBC插入表順序
主要的JDBC操作類,執行sql順序:
基本順序:
記錄工作內容
插入觸發器列表
對應類型trigger規則入庫
存儲已觸發job信息和trigge信息
Simple_trigger :插入順序
qrtz_job_details ---> qrtz_triggers ---> qrtz_simple_triggers
qrtz_fired_triggers
Cron_Trigger:插入順序
qrtz_job_details ---> qrtz_triggers ---> qrtz_cron_triggers
qrtz_fired_triggers
-
為什么要使用cron表達式
我們之前提到 有五種觸發器歸我們使用
其中常用的 有 SimpleTrigger 和 CronTrigger
-
SimpleTrigger 是完全指定的時間反復進行工作的時間表
-
-
CronTrigger 卻擁有着 充分的可根據日歷預定的 方案 且它包含Simple方案中的 初始啟動時間
例如:
-
每個星期五中午
-
每個工作日的早上10:30
-
周三周五 9:00-10:00 每五分鍾一次
-
-
Cron Expressions
Cron 表達式並不是只是使用在 Quartz中的 ,實際上它作為一種專門的表達式也應用在Linux的定時任務中 ,以及在java中Spring的@Scheduled注解 也都使用了
Cron表達式是 字符串形式
Cron本質上是由七個 子表達式,描述個別細節的時間表 而這些子表達式是由空格分開的
子表達式:
位置 意義 有效值 可用特殊字符 1 Seconds 0-59 , - * / 2 Minutes 0-59 , - * / 3 Hours 0 - 23 , - * / 4 Day-of-Month 1 - 31 ( 注意一些特別的月份) , - * / ? L W 5 Month 0 - 11 或 字符串 “JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV DEC” , - * / 6 Day-of-Week(每周) 1 - 7 或 字符串“SUN, MON, TUE, WED, THU, FRI, SAT”表示 * 注意: 1==SUN , - * / ? L # 7 Year(年 可選字段) empty 或者 1970-2099 , - * / -
特殊字符
顯然通過子表達式並不能寫出一個 重復執行的表達式
而特殊字符就是來解決當前問題的
特殊字符 :
符號 表示 舉例說明 / 每 與當前子表達式結合使用占用一個子表達式位置 例: "3/15" 放在第二個子表達式位上, 表示第三分鍾開始執行,每15分鍾執行一次 ? 某一天 只存在與 Day-of-Month 和 Day-of-Week 中使用,來解決 這兩個表達式的沖突問題 在其中一個子表達式有值的情況下 ?寫在另一個表達式上表示匹配任意值,這樣我們就不會再用* 去來表示匹配任意值了 例: 每月15號的早上4點 : "0 0 4 15 * ?" 每周五晚上11點: "0 0 23 ? * FRI" L 每月 或每周 的最后一天 只存在與 Day-of-Month 和 Day-of-Week 中使用, 在 Day-of-Month 子表達式中,“L”表示一個月的最后一天 在 Day-of-Week 子表達式中,“L”表示一個星期的最后一天,也就是SAT 例: “0 15 10 ? * 6L” 表示 每月最后一個星期五10:15分運行。 "0 15 10 2L * ?" 表示 每月倒數第二天10:15分運行。 W 最近工作日 只存在與 Day-of-Month 最近的工作日: 例: "0 15 10 15W * ?" 每個月距離15日最近的工作日 如 15日是周六則執行時間是14日 若15日是周日 則執行時間是16 如15號是工作日就15執行 就近匹配不會跨出當前月 # 第幾個星期幾 只存在與 Day-of-Week 中 每月第n個工作日 例:“0 15 10 ? * 6#3” 表示每個月第三個星期五 “0 15 10 ? * 4#2” 表示每個月第二個星期三 , 多個 例: "0 0 0,13,18,21 * * ?": 每天的0點、13點、18點、21點都執行一次: - 區間 例: "0 0-5 14 * * ?" : 在每天下午2點到下午2:05期間的每1分鍾觸發 * 補位符 補位 但是 注意: Day-of-Month 和 Day-of-Week 肯定有一個為 ? 也不能兩個 ? 綜合例子:
"0 0/30 0-4 ? 3,7 5#2 2018":
30分鍾執行一次
凌晨的0-4 點
每個月
3 月和 7月
第二個周四
2018年
: 2018年 的三月和7月的第二個周四的凌晨0-4點 開始每30分鍾執行一次
"0 30 4 10LW * ?":
第四位是 Day-of-Month L在此表示 每個月最后
10L表示每月的倒數第十天 (不一定是21號 月份不同倒數的第幾天也就不同 ) W表示 附近的工作日
所以表示每個月離倒數第十天最近的工作日的凌晨4點30分執行一次
-