Quartz定時任務框架(二) Quartz詳解
目錄
Scheduler排程程式、SchedulerFactory排程程式工廠
Quartz API
- Scheduler : 和排程程式互動的主要介面
- Job : 由排程程式執行的一個用來擴充套件的介面,execute方法裡面執行的是job的具體行為
- JobDetail : 定義jobs的例項
- Trigger: 定義排程程式上的job的執行時間,用來設定任務什麼時間觸發
- JobBuilder: 用來建立或者定義JobDetail例項
- TriggerBuilder : 用來建立Trigger例項
Scheduler排程程式、SchedulerFactory排程程式工廠
scheduler排程程式
Scheduler維護一個jobDetails和triggers的登錄檔,當時間一到就會觸發job執行
排程程式Scheduler可以通過SchedulerFactory工廠進行建立。一個已經建立的Scheduler可以通過SchedulerFactory獲取。
Scheduler建立後只是出於待機狀態,呼叫scheduler.start()方法啟動,scheduler.shutdown方法關閉,isShutdown檢查狀態。
Scheduler呼叫scheduleJob方法將job加入排程,並在start方法執行後,觸發job執行。
SchedulerFactory
SchedulerFactory有兩個預設的實現類:DirectSchedulerFactory和StdSchedulerFactory
* DirectSchedulerFactory
DirectSchedulerFactory是一個org.quartz.SchedulerFactory的單例實現。
這裡有一些使用DirectSchedulerFactory的示例程式碼段:
示例1:你可以使用createVolatileScheduler方法去建立一個不需要寫入資料庫的排程程式例項:
//建立一個擁有10個執行緒的排程程式
DirectSchedulerFactory.getInstance().createVolatileScheduler(10);
//記得啟用該排程程式
DirectSchedulerFactory.getInstance().getScheduler().start();
另一種,建立方式:
public void createScheduler(String schedulerName, String schedulerInstanceId, ThreadPool threadPool, JobStore jobStore, String rmiRegistryHost, int rmiRegistryPort)
示例程式碼:
// 建立執行緒池
SimpleThreadPool threadPool = new SimpleThreadPool(maxThreads, Thread.NORM_PRIORITY);
threadPool.initialize();
// 建立job儲存器
JobStore jobStore = new RAMJobStore();
//使用所有引數建立排程程式
DirectSchedulerFactory.getInstance().createScheduler("My Quartz Scheduler", "My Instance", threadPool, jobStore, "localhost", 1099);
// 不要忘了呼叫start()方法來啟動排程程式
DirectSchedulerFactory.getInstance().getScheduler("My Quartz Scheduler", "My Instance").start();
也可以使用jdbcjobstore
DBConnectionManager.getInstance().addConnectionProvider("someDatasource", new JNDIConnectionProvider("someDatasourceJNDIName"));
JobStoreTX jdbcJobStore = new JobStoreTX(); jdbcJobStore.setDataSource("someDatasource"); jdbcJobStore.setPostgresStyleBlobs(true); jdbcJobStore.setTablePrefix("QRTZ_"); jdbcJobStore.setInstanceId("My Instance");
* StdSchedulerFactory
StdSchedulerFactory是org.quartz.SchedulerFactory的實現類,它是基於Quartz屬性檔案建立Quartz Scheduler 排程程式的。之前的入門案例使用的就是StdSchedulerFactory,因為我們指定了屬性檔案quartz.properties。
預設情況下是載入當前工作目錄下的”quartz.properties”屬性檔案。如果載入失敗,會去載入org/quartz包下的”quartz.properties”屬性檔案。我們使用JD-GUI反編譯工具開啟quartz.jar,可以在org/quartz包下找到其預設的屬性檔案的配置資訊
預設的quartz.properties中的配置資訊
# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
#
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
org.quartz.jobStore.misfireThreshold: 60000
org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
Job & JobDetail
Job是用來定義任務的執行行為,JobDetail則是用來建立並告知scheduler對應job的各種屬性,JobDetail使用JobBuilder.newJob 建立,建立的時候必須知道job的實現型別。
任務Job有一個名稱name 和組group 來關聯。在一個Scheduler中這二者的組合必須是唯一的。
觸發器任務計劃執行表的執行”機制”。多個觸發器可以指向同一個工作,但一個觸發器只能指向一個工作。
JobDetail job = JobBuilder.newJob (HelloJob.class).withIdentity("job1", "group1")
.build();
public class HelloJob implements Job{
public HelloJob(){}
@Override
public void execute(JobExecutionContext paramJobExecutionContext)
throws JobExecutionException {
System.err.println("["+Thread.currentThread().getName()+"]"+"Hello World! MyJob is executing.");
}
}
每次scheduler執行job的execute方法都會建立一個新的例項,job執行完將它進行回收處理
當使用預設的SchedularFactory實現時,Job的實現類必須有一個無引數的構造器
Job的實現類中,定義一些狀態變數是沒有任何意義的,因為值不能在任務執行期間保留,因為每次執行一次,都會建立新的job例項,執行完畢就會銷燬。
JobDataMap
JobDataMap是JobDetail實體的一部分,通過它能夠了解Job在執行中的狀態,並且用來儲存一些和job執行過程中可用的資料
JobDataMap是map的一個實現類,提供了一些方法來儲存和檢索原始型別的資料
1. 在JobDatail建立的時候可以將資料放到JobDataMap中,在將job加到任務排程之前
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.usingJobData("name", "hello world! ")//usingJobData方法將資料放到jobDataMap中
.usingJobData("age", 110l)
.usingJobData("flag", false)
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(1)
.repeatForever())
.build();
2. 在Job的執行期間將資料取出
public class HelloJob implements Job{
public HelloJob(){}
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
String name = jobDataMap.getString("name");
long age = jobDataMap.getLong("age");
boolean flag = jobDataMap.getBoolean("flag");
System.out.println("name:"+name+",age:"+age+",flag:"+flag);
System.err.println("["+Thread.currentThread().getName()+"]"+"Hello World! MyJob is executing.");
}
}
儲存進去jobdataMap的資料將會被序列化,可能出現序列化的問題。顯然標準的java型別儲存是安全的,但是如果存放的是序列化自定義的物件,就可能出現序列化問題。
在存放key和字串的模式中,可以將javadatamap作為資料儲存,而不是存放基本型別資料,從而解決消除序列化出現的問題。
另外,Trigger也能和jobdatamap關聯,當使用多個Trigger設定一個job時,對於每個trigger都可以通過jobdataMap提供獨立的輸入。
通過JobExecutionContext能夠獲取javadatamap,是jobdetail和trigger關聯的javadatamap的合併,這這樣獲取的jobdataMap能夠獲取到jobDatail和Trigger觸發器中的值。
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.usingJobData("name", "hello world! ")//usingJobData方法將資料放到jobDataMap中
.usingJobData("age", 110l)
.usingJobData("flag", false)
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(1)
.repeatForever())
.build();
public void execute(JobExecutionContext context)
throws JobExecutionException {
JobDataMap jobDataMap = context.getMergedJobDataMap();
}
Job例項化的過程
可以建立一個job類,然後建立多個jobDetail,每個jobDetail都有自己的設定和jobdatamap,最後加到scheduler排程程式中。
舉個例子:你可以建立一個SalesReportJob的job類,作為銷售報表使用,在javadatamap中指定銷售報表的名稱和依據,然後建立這個job的多個jobDetail例項,例如 SalesReportForJoe和SalesReportForMik
重要:當觸發器時間到了,就會載入關聯的JobDetail,依賴於JobFactory的scheduler的配置進行例項化。JobFactory建立新的job例項,並呼叫job中set方法將值設定到jobdatamap的對應key上。jobFactory也可以擴充套件,通過ioc,di完成job例項的構建。
job的註解宣告和併發
@DisallowConcurrentExecution: 新增在job類上,告知quartz在多執行緒環境下不執行job的多個例項。
注意,這個約束是基於jobDetail而不是job類,上面的SalesReportJob的job類,定義了多個SalesReportFroJoe和SalesReportForMik,這兩個jobDetail例項,這就意味在多執行緒環境下, 只能執行一個SalesReportForJoe和一個SalesReportForMik定義的job.
@PersistJobDataAfterExecution: 當執行一次execute完畢後,更新jobdatamap中的資料,這樣下次執行execute方法,檢索的是更新的值,而不是原始的值。
如果使用@PersistJobDataAfterExecution註解,強烈建議配合使用@DisallowConcurrentExecution,避免在多執行緒環境下, 多個job導致的資料問題。
job的其他屬性
- 持久化 - 如果一個任務不是持久化的,則當沒有觸發器關聯它的時候,Quartz會從scheduler中刪除它。
- 請求恢復 - 如果一個任務請求恢復,一般是該任務執行期間發生了系統崩潰或者其他關閉程式的操作,當服務再次啟動的時候,會再次執行該任務。這種情況下,JobExecutionContext.isRecovering()會返回true
Trigger觸發器
TriggerBuilder 用於建立觸發器Trigger。如果你沒有呼叫withSchedule(..) 方法,會使用預設的schedule 。如果沒有使用withIdentity(..) 會自動生成一個觸發器名稱給你。可以在觸發器使用TriggerBuilder進行例項化的同時設定一些屬性
jobkey: 當觸發器觸發的時候,執行的job
starttime: 觸發器開始觸發的時間
endtime: 觸發器結束觸發的時間,比如每5天觸發一次,endtime是7月1號,那麼最後的執行時間是7月5號。
優先順序Priority
設定屬性優先順序,只有starttime相同才有意義。
當一個任務請求恢復,恢復和原始的優先順序一致。
參考:http://www.quartz-scheduler.org/documentation/quartz-2.1.x/tutorials/tutorial-lesson-04.html
https://blog.csdn.net/zixiao217/article/details/53053598
相關文章
- 石英定時任務-quartzquartz
- Quartz定時任務框架(一) 入門案例quartz框架
- Quartz 定時任務管理類quartz
- quartz定時任務時間設定quartz
- 簡單說說Java 定時任務框架---QuartzJava框架quartz
- java Quartz 定時任務管理類Javaquartz
- Spring Scheduler定時任務 + QuartzSpringquartz
- Quartz - Spring整合Quartz實現叢集的定時任務quartzSpring
- Spring Boot 配置 Quartz 定時任務Spring Bootquartz
- Quartz高可用定時任務快速上手quartz
- 普通web整合quartz跑定時任務Webquartz
- Quartz實現動態定時任務quartz
- SpringBoot整合Quartz定時任務Spring Bootquartz
- quartz學習-quartz編碼方式實現定時任務簡例quartz
- 淺談分散式定時任務之quartz分散式quartz
- springboot Quartz 定時任務工具類Spring Bootquartz
- Spring+quartz 實現定時任務Springquartz
- [原始碼分析] 定時任務排程框架 Quartz 之 故障切換原始碼框架quartz
- DolphinScheduler心臟:Quartz的定時任務排程框架深度解析quartz框架
- spring2.0 quartz 靜態定時任務Springquartz
- java 定時任務 quartz 時間表示式Cron總結Javaquartz
- 任務排程框架Quartz快速入門!框架quartz
- Grails整合Quartz外掛實現定時任務(Job)AIquartz
- 使用Spring整合Quartz輕鬆完成定時任務Springquartz
- Spring 整合 Quartz 實現動態定時任務Springquartz
- 一看便知spring+quartz定時任務Springquartz
- NET作業排程(定時任務)-Quartz.Netquartz
- 初識spring與quartz整合實現定時任務Springquartz
- 【1】基於quartz框架和Zookeeper實現叢集化定時任務系統quartz框架
- 定時排程系列之Quartz.Net詳解quartz
- 深入解讀Quartz任務排程器quartz
- Spring+quartz實現動態化定時任務 (轉)Springquartz
- springboot整合Quartz實現動態配置定時任務Spring Bootquartz
- Quartz定時任務框架(三)SimpleTrigger和CronTrigger、最詳細的Cron表示式範例quartz框架
- 一文快速入門任務排程框架-Quartz框架quartz
- 震驚!Windows Service服務和定時任務框架quartz之間原來是這種關係……Windows框架quartz
- springboot+quartz以持久化的方式實現定時任務Spring Bootquartz持久化
- 3分鐘掌握Quartz.net分散式定時任務的姿勢quartz分散式