Quartz 教程

  • 時間:2018-06-27 21:36 作者:丹青筆 來源:丹青筆 閱讀:480
  • 掃一掃,手機訪問
摘要:一、關于 QuartzQuartz logoQuartz 是一個完全由 Java 編寫的開源作業調度框架,為在 Java 應使用程序中進行作業調度提供了簡單卻強大的機制。Quartz 能與 J2EE 與 J2SE 應使用程序相結合也能單獨用。Quartz 允許程序開發人員根據時間的間隔來調度作業。

一、關于 Quartz

Quartz logo
  • Quartz 是一個完全由 Java 編寫的開源作業調度框架,為在 Java 應使用程序中進行作業調度提供了簡單卻強大的機制。
  • Quartz 能與 J2EE 與 J2SE 應使用程序相結合也能單獨用。
  • Quartz 允許程序開發人員根據時間的間隔來調度作業。
  • Quartz 實現了作業和觸發器的多對多的關系,還可以把多個作業與不同的觸發器關聯。

二、Quartz 核心概念

核心組件
  • Scheduler:調度容器
  • Job:Job接口類,即被調度的任務
  • JobDetail :Job的形容類,job執行時的依據此對象的信息反射實例化出Job的具體執行對象。
  • Trigger:觸發器,存放Job執行的時間策略。使用于定義任務調度時間規則。
  • JobStore: 存儲作業和調度期間的狀態
  • Calendar:指定排除的時間點(如排除法定節假日)

job

Job 是一個接口,只有一個方法 void execute(JobExecutionContext context),開發者實現接口來定義任務。JobExecutionContext 類提供了調度上下文的各種信息。Job 運行時的信息保存在 JobDataMap 實例中。例如:

public class HelloJob implements BaseJob {    private static Logger _log = LoggerFactory.getLogger(HelloJob.class);      public HelloJob() { }      public void execute(JobExecutionContext context) throws JobExecutionException {        _log.error("Hello Job執行時間: " + new Date());    }}  

JobDetailImpl 類 / JobDetail 接口

JobDetailImpl類實現了JobDetail接口,使用來形容一個 job,定義了job所有屬性及其 get/set 方法。下面是 job 內部的主要屬性:

屬性名說明
class必需是job實現類(比方JobImpl),使用來綁定一個具體job
namejob 名稱。假如未指定,會自動分配一個唯一名稱。所有job都必需擁有一個唯一name,假如兩個 job 的name重復,則只有最前面的 job 可以被調度
groupjob 所屬的組名
descriptionjob形容
durability能否持久化。假如job設置為非持久,當沒有活躍的trigger與之關聯的時候,job 會自動從scheduler中刪除。也就是說,非持久job的生命期是由trigger的存在與否決定的
shouldRecover能否可恢復。假如 job 設置為可恢復,一旦 job 執行時scheduler發生hard shutdown(比方進程崩潰或者關機),當scheduler重啟后,該job會被重新執行
jobDataMap除了上面常規屬性外,使用戶能把任意kv數據存入jobDataMap,實現 job 屬性的無限制擴展,執行 job 時能用這些屬性數據。此屬性的類型是JobDataMap,實現了Serializable接口,可做跨平臺的序列化傳輸

Trigger

是一個類,形容觸發Job執行的時間觸發規則。主要有 SimpleTriggerCronTrigger 這兩個子類。當僅需觸發一次或者者以固定時間間隔周期執行,SimpleTrigger是最適合的選擇;而CronTrigger則能通過Cron表達式定義出各種復雜時間規則的調度方案:如每早晨9:00執行,周一、周三、周五下午5:00執行等;

以下是 trigger 的屬性:

屬性名屬性類型說明
name所有trigger通使用trigger名稱
group所有trigger通使用trigger所屬的組名
description所有trigger通使用trigger形容
calendarName所有trigger通使用日歷名稱,指定用哪個Calendar類,經常使用來從trigger的調度計劃中排除某些時間段
misfireInstruction所有trigger通使用錯過job(未在指定時間執行的job)的解決策略,默認為MISFIRE_INSTRUCTION_SMART_POLICY。詳見這篇blog^Quartz misfire
priority所有trigger通使用優先級,默認為5。當多個trigger同時觸發job時,線程池可可以不夠使用,此時根據優先級來決定誰先觸發
jobDataMap所有trigger通使用同job的jobDataMap。如果job和trigger的jobDataMap有同名key,通過getMergedJobDataMap()獲取的jobDataMap,將以trigger的為準
startTime所有trigger通使用觸發開始時間,默認為當前時間。決定什么時間開始觸發job
endTime所有trigger通使用觸發結束時間。決定什么時間中止觸發job
nextFireTimeSimpleTrigger私有下一次觸發job的時間
previousFireTimeSimpleTrigger私有上一次觸發job的時間
repeatCountSimpleTrigger私有需觸發的總次數
timesTriggeredSimpleTrigger私有已經觸發過的次數
repeatIntervalSimpleTrigger私有觸發間隔時間

Calendar

org.quartz.Calendarjava.util.Calendar不同,它是少量日歷特定時間點的集合(能簡單地將org.quartz.Calendar看作java.util.Calendar的集合——java.util.Calendar代表一個日歷時間點,無特殊說明后面的Calendar即指org.quartz.Calendar)。一個Trigger能和多個Calendar關聯,以便排除或者包含某些時間點。假設,我們安排每周星期一早上10:00執行任務,但是假如碰到法定的節日,任務則不執行,這時就需要在Trigger觸發機制的基礎上用Calendar進行定點排除。

Scheduler

調度器,代表一個Quartz的獨立運行容器,好比一個『大管家』,這個大管家應該能接受 Job, 而后按照各種Trigger去運行,TriggerJobDetail能注冊到Scheduler中,兩者在Scheduler中擁有各自的組及名稱,組及名稱是Scheduler查找定位容器中某一對象的依據,Trigger的組及名稱必需唯一,JobDetail的組和名稱也必需唯一(但能和Trigger的組和名稱相同,由于它們是不同類型的)。Scheduler定義了多個接口方法,允許外部通過組及名稱訪問和控制容器中Trigger和JobDetail。

image
Scheduler 能將 Trigger 綁定到某一 JobDetail 中,這樣當 Trigger 觸發時,對應的 Job 就被執行。能通過 SchedulerFactory創立一個 Scheduler 實例。Scheduler 擁有一個 SchedulerContext,它相似于 ServletContext,保存著 Scheduler 上下文信息,Job 和 Trigger 都能訪問 SchedulerContext 內的信息。SchedulerContext 內部通過一個 Map,以鍵值對的方式維護這些上下文數據,SchedulerContext 為保存和獲取數據提供了多個 put() 和 getXxx() 的方法。能通過Scheduler# getContext()獲取對應的SchedulerContext實例;

ThreadPool

Scheduler 用一個線程池作為任務運行的基礎設備,任務通過共享線程池中的線程提高運行效率。

進行一個定時任務的簡單實例

public class JobTest implements BaseJob {    private static org.slf4j.Logger log = LoggerFactory.getLogger(JobTest.class);    @Override    public void execute(JobExecutionContext context) throws JobExecutionException {        log.error("JobTest 執行時間: " + new Date());    }}
@Testpublic void quartzTest() throws SchedulerException{    // 1. 創立 SchedulerFactory    SchedulerFactory factory = new StdSchedulerFactory();    // 2. 從工廠中獲取調度器實例    Scheduler scheduler = factory.getScheduler();    // 3. 引進作業程序    JobDetail jobDetail = JobBuilder.newJob(JobTest.class).withDescription("this is a ram job") //job的形容            .withIdentity("jobTest", "jobTestGrip") //job 的name和group            .build();    long time=  System.currentTimeMillis() + 3*1000L; //3秒后啟動任務    Date statTime = new Date(time);    // 4. 創立Trigger    //用SimpleScheduleBuilder或者者CronScheduleBuilder    Trigger trigger = TriggerBuilder.newTrigger()            .withDescription("this is a cronTrigger")            .withIdentity("jobTrigger", "jobTriggerGroup")            //.withSchedule(SimpleScheduleBuilder.simpleSchedule())            .startAt(statTime)  //默認當前時間啟動            .withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?")) //兩秒執行一次            .build();    // 5. 注冊任務和定時器    scheduler.scheduleJob(jobDetail, trigger);    // 6. 啟動 調度器    scheduler.start();    _log.info("啟動時間 : " + new Date());}

三、Quartz 設計分析

quartz.properties文件

Quartz 有一個叫做quartz.properties的配置文件,它允許你修改框架運行時環境。缺省是用 Quartz.jar 里面的quartz.properties 文件。你應該創立一個 quartz.properties 文件的副本并且把它放入你工程的 classes 目錄中以便類裝載器找到它。

// 調度標識名 集群中每一個實例都必需用相同的名稱 (區分特定的調度器實例) 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 // 線程優先級 // threadPriority 屬性的最大值是常量 java.lang.Thread.MAX_PRIORITY,等于10。最小值為常量 java.lang.Thread.MIN_PRIORITY,為1org.quartz.threadPool.threadPriority : 5// 自創立父線程 //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

Quartz 調度器

Quartz框架的核心是調度器。調度器負責管理Quartz應使用運行時環境。啟動時,框架初始化一套worker線程,這套線程被調度器使用來執行預約的作業。這就是 Quartz 怎么可以并發運行多個作業的原理。Quartz 依賴一套松耦合的線程池管理部件來管理線程環境。

兩種作業存儲方式

1. RAMJobStore

- 通常的內存來持久化調度程序信息。這種作業存儲類型最容易配置、構造和運行。- 由于這種方式的調度程序信息是被分配到 JVM 內存中,所以,當應使用程序中止運行時,所有調度信息將被丟失。假如你需要在重新啟動之間持久化調度信息,則將需要第二種類型的作業存儲。 

2. JDBC作業存儲

- 需要JDBC驅動程序和后端數據庫來持久化調度程序信息(支持集群)
表關系和解釋
表關系
表名稱 | 說明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   

利使用 SpringBoot + Quartz 搭建的界面化的 Demo

在網上找到一個搭好的 Demo,感謝大神!原文: Spring Boot集成持久化Quartz定時任務管理和界面展現

本工程所使用到的技術或者工具

Spring Boot
Mybatis
Quartz
PageHelper
VueJS
ElementUI
MySql數據庫

先看圖:

效果圖.png
新建任務.png

源碼地址

  • 我的github
  • 我的碼云
  • 原項目github

參考資料

  • quartz原理揭秘和源碼解讀
  • quartz由淺入深
  • Quartz官方文檔
  • Spring Boot集成持久化Quartz定時任務管理和界面展現
  • 全部評論(0)
上一篇:拖拽交換
下一篇:ES6系列之Symbol
最新發布的資訊信息
【系統環境|數據庫】零基礎如何快速學好大數據?(2019-06-29 12:27)
【系統環境|Linux】零基礎如何學好大數據?必備需要學習知識(2019-06-18 11:54)
【系統環境|】Hadoop環境中管理大數據存儲八大技巧(2019-06-15 11:01)
【系統環境|服務器應用】現在國內IT行業是不是程序員過多了?(2019-06-11 06:34)
【系統環境|服務器應用】新貴 Flutter(2) 自己設置 Widget(2019-06-11 06:34)
【系統環境|服務器應用】Android完整知識體系路線(菜鳥-資深-大牛必進之路)(2019-06-11 06:34)
【系統環境|服務器應用】Java程序員小伙經歷三個月備戰,終獲阿里offer(2019-06-11 06:34)
【系統環境|服務器應用】每日一問:談談對 MeasureSpec 的了解(2019-06-11 06:34)
【系統環境|服務器應用】【科普】晶體管-1(2019-06-11 06:34)
【系統環境|服務器應用】一個很多人都會答錯的java基礎題(2019-06-11 06:33)
手機二維碼手機訪問領取大禮包
返回頂部
双色球号码300期遗传走势图