Quartz是一個開源的作業調度框架,完全由java寫的,你能通過它創建簡單或者復雜的任務。他能提供巨大的靈活性,但又不犧牲簡單性。
Quartz的核心概念 :調度器、觸發器、作業
調度器(Scheduler)
Scheduler負責管理Quartz的運行環境,Quartz它是基于多線程架構的,它啟動的時候會初始化一套線程,這套線程會用來執行一些預置的作業。
要創建一個作業并能夠被觸發調用,必須在Scheduler上面注冊一個JobDetail和Trigger。
Scheduler提攜了所有Trigger和JobDetail,使它們協調工作。這些Trigger和JobDetail通過自身的name和group屬性區分。
Scheduler 由SchedulerFactory產生,我們可以通過以下方式獲取Scheduler的實例:
//從ServletContext上下文中查找SchedulerFactory
SchedulerFactory factory = (SchedulerFactory)
ServletActionContext.getServletContext().getAttribute("org.quartz.impl.StdSchedulerFactory.KEY");
//獲取Scheduler對象
Scheduler defScheduler = factory.getScheduler();
作業
Job
任務,其實就是一個接口。要創建一個任務,必須得實現這個接口。該接口只有一個execute方法,任務每次被調用的時候都會執行這個execute方法的邏輯。
public class TestJob impletemens org.quartz.Job{
@Override
public void execute(JobExecutionContext context) throws JobExecutionException{
// you business logic
// …
System.out.println("########### this is testJob running ############");
}
}
JobDetail
JobDetail 用來保存我們作業的詳細信息。一個JobDetail可以有多個Trigger,但是一個Trigger只能對應一個JobDetail。下面是JobDetail的一些常用的屬性和含義
參數名 |
類型 |
備注 |
name |
String |
任務的名稱,必須 |
group |
String |
任務所在組,默認為DEFAULT |
jobClass |
Class |
任務的實現類,必須 |
description |
String |
描述 |
jobDataMap |
JobDataMap |
用來給作業提供數據支持的數據結構 |
volatility |
Boolean |
重啟應用之后是否刪除任務的相關信息,默認false |
durability |
Boolean |
任務完成之后是否依然保留到數據庫,默認false |
shouldRecover |
Boolean |
應用重啟之后時候忽略過期任務,默認false |
jobListeners |
Set |
監聽器 |
JobDataMap
這是一個給作業提供數據支持的數據結構,使用方法和java.util.Map一樣,非常方便。當一個作業被分配給調度器時,JobDataMap實例就隨之生成。
Job有一個StatefulJob子接口,代表有狀態的任務,該接口是一個沒有方法的標簽接口,其目的是讓Quartz知道任務的類型,以便采用不同的執行方案。無狀態任務在執行時擁有自己的JobDataMap拷貝,對JobDataMap的更改不會影響下次的執行。而有狀態任務共享共享同一個JobDataMap實例,每次任務執行對JobDataMap所做的更改會保存下來,后面的執行可以看到這個更改,也即每次執行任務后都會對后面的執行發生影響。
正因為這個原因,無狀態的Job可以并發執行,而有狀態的StatefulJob不能并發執行,這意味著如果前次的StatefulJob還沒有執行完畢,下一次的任務將阻塞等待,直到前次任務執行完畢。有狀態任務比無狀態任務需要考慮更多的因素,程序往往擁有更高的復雜度,因此除非必要,應該盡量使用無狀態的Job。
如果Quartz使用了數據庫持久化任務調度信息,無狀態的JobDataMap僅會在Scheduler注冊任務時保持一次,而有狀態任務對應的JobDataMap在每次執行任務后都會進行保存。
JobDataMap實例也可以與一個觸發器相關聯。這種情況下,對于同一作業的不同觸發器,我們可以在JobDataMap中添加不同的數據,以便作業在不同時間執行時能夠提供更為靈活的數據支持(學校上午放眼保健操錄音第一版,下午放第二版)。
不管是有狀態還是無狀態的任務,在任務執行期間對Trigger的JobDataMap所做的更改都不會進行持久,也即不會對下次的執行產生影響。