前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。
? Quartz 在開源任務調度框架中的翹首,它提供了強大任務調度機制,難能可貴的是它同時保持了使用的簡單性。Quartz 允許開發人員靈活地定義觸發器的調度時間表,并可以對觸發器和任務進行關聯映射。
??????? 此外,Quartz提供了調度運行環境的持久化機制,可以保存并恢復調度現場,即使系統因故障關閉,任務調度現場數據并不會丟失。此外,Quartz還提供了組件式的偵聽器、各種插件、線程池等功能。
一、Quartz功能概述
Quartz是一個開源的任務調度系統,它能用來調度很多任務的執行。
運行環境
- Quartz 能嵌入在其他應用程序里運行。
- Quartz 能在一個應用服務器里被實例化(或servlet容器), 并且參與XA事務
- Quartz能獨立運行(通過JVM),或者通過RMI
- Quartz能被集群實例化
任務調度
當一個指定給任務的觸發器發生時,任務就被調度執行.觸發器能被創建為:
- 一天的某個時間(精確到毫秒級)
- 一周的某些天
- 一個月的某些天
- 一年的某些天
- 不在一個Calendar列出的某些天 (例如工作節假日)
- 在一個指定的次數重復
- 重復到一個指定的時間/日期
- 無限重復
- 在一個間隔內重復
能夠給任務指定名稱和組名.觸發器也能夠指定名稱和組名,這樣可以很好的在調度器里組織起來.一個加入到調度器里的任務可以被多個觸發器注冊。在J2EE環境里,任務能作為一個分布式(XA)事務的一部分來執行。
任務執行
- 任務能夠是任何實現Job接口的Java類。
- 任務類能夠被Quartz實例化,或者被你的應用框架。
- 當一個觸發器觸發時,調度器會通知實例化了JobListener 和TriggerListener 接口的0個或者多個Java對象(監聽器可以是簡單的Java對象, EJBs, 或JMS發布者等). 在任務執行后,這些監聽器也會被通知。
- 當任務完成時,他們會返回一個JobCompletionCode ,這個代碼告訴調度器任務執行成功或者失敗.這個代碼 也會指示調度器做一些動作-例如立即再次執行任務。
任務持久化
- Quartz的設計包含JobStore接口,這個接口能被實現來為任務的存儲提供不同的機制。
- 應用JDBCJobStore, 所有被配置成“穩定”的任務和觸發器能通過JDBC存儲在關系數據庫里。
- 應用RAMJobStore, 所有任務和觸發器能被存儲在RAM里因此不必在程序重起之間保存-一個好處就是不必使用數據庫。
事務
- 使用JobStoreCMT(JDBCJobStore的子類),Quartz 能參與JTA事務。
- Quartz 能管理JTA事務(開始和提交)在執行任務之間,這樣,任務做的事就可以發生在JTA事務里。
集群
- Fail-over.
- Load balancing.
監聽器和插件
- 通過實現一個或多個監聽接口,應用程序能捕捉調度事件來監控或控制任務/觸發器的行為。
- 插件機制可以給Quartz增加功能,例如保持任務執行的歷史記錄,或從一個定義好的文件里加載任務和觸發器。
- Quartz 裝配了很多插件和監聽器。
?
二、Quartz體系結構
?
Quartz對任務調度的領域問題進行了高度的抽象,提出了調度器、任務和觸發器這3個核心的概念,并在org.quartz通過接口和類對重要的這些核心概念進行描述:
●Job
?????? 是一個接口,只有一個方法voidexecute(JobExecutionContext context),開發者實現該接口定義運行任務,JobExecutionContext類提供了調度上下文的各種信息。Job運行時的信息保存在 JobDataMap實例中;
●JobDetail
??????? Quartz在每次執行Job時,都重新創建一個Job實例,所以它不直接接受一個Job的實例,相反它接收一個Job實現 類,以便運行時通過newInstance()的反射機制實例化Job。因此需要通過一個類來描述Job的實現類及其它相關的靜態信息,如Job名字、描 述、關聯監聽器等信息,JobDetail承擔了這一角色。
通過該類的構造函數可以更具體地了解它的功用:JobDetail(java.lang.String name, java.lang.String group,java.lang.Class jobClass),該構造函數要求指定Job的實現類,以及任務在Scheduler中的組名和Job名稱;
●Trigger
?????? 是一個類,描述觸發Job執行的時間觸發規則。主要有SimpleTrigger和CronTrigger這兩個子類。當僅需觸 發一次或者以固定時間間隔周期執行,SimpleTrigger是最適合的選擇;而CronTrigger則可以通過Cron表達式定義出各種復雜時間規 則的調度方案:如每早晨9:00執行,周一、周三、周五下午5:00執行等;
●Calendar
?????? org.quartz.Calendar和java.util.Calendar不同,它是一些日歷特定時間點的集合(可以簡 單地將org.quartz.Calendar看作java.util.Calendar的集合——java.util.Calendar代表一個日歷時間點,無特殊說明后面的Calendar即指org.quartz.Calendar)。一個Trigger可以和多個Calendar關聯,以便排除或 包含某些時間點。
假設,我們安排每周星期一早上10:00執行任務,但是如果碰到法定的節日,任務則不執行,這時就需要在Trigger觸發機制的基礎上使用 Calendar進行定點排除。針對不同時間段類型,Quartz在org.quartz.impl.calendar包下提供了若干個Calendar 的實現類,如AnnualCalendar、MonthlyCalendar、WeeklyCalendar分別針對每年、每月和每周進行定義;
●Scheduler
??????? 代表一個Quartz的獨立運行容器,Trigger和JobDetail可以注冊到Scheduler中,兩者在 Scheduler中擁有各自的組及名稱,組及名稱是Scheduler查找定位容器中某一對象的依據,Trigger的組及名稱必須唯一,JobDetail的組和名稱也必須唯一(但可以和Trigger的組和名稱相同,因為它們是不同類型的)。Scheduler定義了多個接口方法, 允許外部通過組及名稱訪問和控制容器中Trigger和JobDetail。
??????? Scheduler可以將Trigger綁定到某一JobDetail中,這樣當Trigger觸發時,對應的Job就被執行。一個Job可以對應 多個Trigger,但一個Trigger只能對應一個Job。可以通過SchedulerFactory創建一個Scheduler實例。 Scheduler擁有一個SchedulerContext,它類似于ServletContext,保存著Scheduler上下文信息,Job和 Trigger都可以訪問SchedulerContext內的信息。SchedulerContext內部通過一個Map,以鍵值對的方式維護這些上下文數據,SchedulerContext為保存和獲取數據提供了多個put()和getXxx()的方法。可以通過Scheduler# getContext()獲取對應的SchedulerContext實例;
三、入門實例
本文工程免費下載
新建一個Java project.
導入相應的包
執行業務邏輯的Job
?
- package com.mucfc;
- import java.text.SimpleDateFormat;
- import java.util.Date;
-
- import org.quartz.Job;
- import org.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
- /**
- *Quartz事件類
- *作者 林炳文(ling20081005@126.com 博客:http://blog.csdn.net/evankaka)
- *時間 2015.4.29
- */
- public class Quartz implements Job{
- /**
- * 事件類,處理具體的業務
- */
- @Override
- public void execute(JobExecutionContext arg0) throws JobExecutionException {
- System.out.println("Hello quzrtz "+
- new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ").format(new Date()));
- }
-
- }
任務調度
?
?
- package com.mucfc;
- import org.quartz.JobBuilder;
- import org.quartz.JobDetail;
- import org.quartz.Scheduler;
- import org.quartz.SchedulerException;
- import org.quartz.SimpleScheduleBuilder;
- import org.quartz.Trigger;
- import org.quartz.TriggerBuilder;
- import org.quartz.impl.StdSchedulerFactory;
- /**
- *Quartz定時執行事件
- *作者 林炳文(ling20081005@126.com 博客:http://blog.csdn.net/evankaka)
- *時間 2015.4.29
- */
- public class QuartzTest {
-
- public static void main(String[] args) {
- QuartzTest quartzTest=new QuartzTest();
- quartzTest.startSchedule();
-
- }
-
- public void startSchedule() {
- try {
- // 1、創建一個JobDetail實例,指定Quartz
- JobDetail jobDetail = JobBuilder.newJob(Quartz.class)
- // 任務執行類
- .withIdentity("job1_1", "jGroup1")
- // 任務名,任務組
- .build();
- //2、創建Trigger
- SimpleScheduleBuilder builder=SimpleScheduleBuilder.simpleSchedule()
- //設置間隔執行時間
- .withIntervalInSeconds(5)
- //設置執行次數
- .repeatForever();
- Trigger trigger=TriggerBuilder.newTrigger().withIdentity(
- "trigger1_1","tGroup1").startNow().withSchedule(builder).build();
- //3、創建Scheduler
- Scheduler scheduler=StdSchedulerFactory.getDefaultScheduler();
- scheduler.start();
- //4、調度執行
- scheduler.scheduleJob(jobDetail, trigger);
- try {
- Thread.sleep(60000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- scheduler.shutdown();
-
- } catch (SchedulerException e) {
- e.printStackTrace();
- }
- }
- }
(注意這里,通過靜態import,直接就newJob****。)
?
?
?
輸出結果:
這里要注意,定時事件不是在主線程中執行的,而是會開另外的線程來執行。并且當主線程休眠1分鐘后,會把定時事件給關了,這里即使不會無限執行的事件,也要用shutdown();關閉掉,要不定時事件的線程不會釋放資源!
轉自:http://blog.csdn.net/evankaka