Quartz 是 OpenSymphony 開源組織在任務調度領域的一個開源項目,徹底基於 Java 實現。該項目於 2009 年被 Terracotta 收購,目前是 Terracotta 旗下的一個項目。它是一個而安全有java辨析額的開源做業調度框架。java
1.強大的調度功能,例如支持豐富多樣的調度方法,能夠知足各類常規及特殊需求;數據庫
2.靈活的應用方式,例如支持任務和調度的多種組合方式,支持調度數據的多種存儲方式;安全
3.分佈式和集羣能力,Terracotta 收購後在原來功能基礎上做了進一步提高;框架
4.另外,做爲 Spring 默認的調度框架,Quartz 很容易與 Spring 集成實現靈活可配置的調度功能。分佈式
開發企業級任務調度應用:Quartz 就是啓動定時任務的框架 !! !測試
利用 Quartz 進行開發至關簡單,只須要將下載開發包中的 quartz-all-1.8.4.jar 加入到 classpath 便可。根據筆者的經驗,對於任務調度功能比較複雜的企業級應用來講,最好在開發階段將 Quartz 的源代碼導入到開發環境中來。一方面能夠經過閱讀源碼瞭解 Quartz 的實現機理,另外一方面能夠經過擴展或修改 Quartz 的一些類來實現某些 Quartz 尚不提供的功能。ui
1.Quartz定時調度框架使用說明
1) Job任務編碼
具體要執行任務的程序。好比發短信,發郵件,訪問數據庫,同步數據,數據的清洗,本項目中使用在宣傳活動定時過時的模塊。spa
2)Trigger觸發器 code
a)做用:它是來執行工做任務,在什麼條件下觸發,什麼時間執行,多久執行一次。
b)四大類型:SimpleTrigger,CronTirgger,DateIntervalTrigger, 和 NthIncludedDayTrigger。
SimpleTrigger 通常用於實現每隔必定時間執行任務,以及重複多少次,如每 2 小時執行一次,重複執行 5 次。SimpleTrigger 內部實現機制是經過計算間隔時間來計算下次的執行時間,這就致使其不適合調度定時的任務。例如咱們想天天的 1:00AM 執行任務,若是使用 SimpleTrigger 的話間隔時間就是一天。注意這裏就會有一個問題,即當有 misfired 的任務而且恢復執行時,該執行時間是隨機的(取決於什麼時候執行 misfired 的任務,例如某天的 3:00PM)。這會致使以後天天的執行時間都會變成 3:00PM,而不是咱們原來指望的 1:00AM。
CronTirgger 相似於 LINUX 上的任務調度命令 crontab,即利用一個包含 7 個字段的表達式來表示時間調度方式。例如,"0 15 10 * * ? *" 表示天天的 10:15AM 執行任務。對於涉及到星期和月份的調度,CronTirgger 是最適合的,甚至某些狀況下是惟一選擇。例如,"0 10 14 ? 3 WED" 表示三月份的每一個星期三的下午 14:10PM 執行任務。讀者能夠在具體用到該 trigger 時再詳細瞭解每一個字段的含義。
3)scheduler定時器
Scheduler就是用來啓動Trigger去執行Job。
在 Quartz 中, Scheduler 由 scheduler 工廠建立:DirectSchedulerFactory 或者 StdSchedulerFactory。 第二種工廠 StdSchedulerFactory 使用較多,由於 DirectSchedulerFactory 使用起來不夠方便,須要做許多詳細的手工編碼設置。 Scheduler 主要有三種:RemoteMBeanScheduler, RemoteScheduler 和 StdScheduler。
2.簡單案例
【使用步驟】:
1.導入quartz和quartz-job 的jar包
2.定義job任務類,該任務類須要實現接口Job,並重寫方法
3.建立定時器對象
StdSchedulerFactory.getDefaultSchedule()得到的是一個定時器Scheduler對象
4.建立一個工做(jobDetail)對象實例,設置它的名字、組(當trigger去觸發job的時候,是按照名字和分組去進行觸發的)
a.JobBuilder.newJob(HelloJob.class) //建立builder,(jobDetail的預準備對象)
b.經過builder調用withIdentity()去設置builder的名字和分組
c.最後經過build()方法得到一個jobDetail對象
5.定義一個觸發器trigger對象,用來執行jobDetail
a.TriggerBuilder.newTrigger() //建立一個觸發器trigger對象,
b.withIdentity(「trigger_1」, 「group_1」) //設置觸發器的名字和分組
c.startNow() //設置觸發器開始執行JobDetail的起始時間,還有startAt() 在指定的時間去執行
//設置以哪一種方式執行JobDetail
[有兩種方式]
一種是:SimpleScheduleBuilder 簡單任務的重複執行
另外一種是:CronTrigger 按日曆觸發任務
//以及執行一次JobDetail的間隔時間,以及執行到何時
d.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5))
e.build() 最終得到一個Trigger對象
6.開啓定時任務
scheduler.start();
【CronTrigger 按日曆觸發任務 簡介】 [Cron表達式]: 由7個子表達式組成的字符串,每一個子表達式都描述了一個單獨的日程細節,這些子表達式用空格分割,分別表示: 1.Seconds 秒 2.Minutes 分 3.Hours 小時 4.Day-of-Month 月中的天,可選值(1-31) 5.Month 哪個月,可選值(JAN、FEB、MAR、APR、MAY、JUN、JUL、AUG、SEP、OCT、NOV、DEC) 6.Day-of-Week 週中的天,可選值(SUN、MON、TUE、WED、THU、FRI、SAT) 7.Year 年(可選的域,無關緊要) [特殊字符] '/' 用來表示增量 '?' 用來表示沒有執行的值,可是,四、6不能同時使用'?' 它們必須指定一項 不然會報錯 '*' 通配符,表示全部可能的值 [Cron表達式示例]: 0 0 12 ? * WED -------表示每週三的中午12:00 0/15若是放在第一位,表示從0開始,每15分鐘執行一次
【使用案例1】: [建立job類,使用SimpleSchedulerBuilder]: import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; //quartz的任務 public class HelloJob implements Job { public static int i = 0; public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("hello quartz............"+(i++)); } } [測試類]: import org.junit.Test; 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; import job.HelloJob; //在測試的時候遇到一個問題,若是使用JUnit來進行測試的話,進程會死掉 public class HelloScheduler { public static void main(String[] args) throws SchedulerException { //建立一個定時器對象 Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); //定義一個工做對象 JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("job_1","group1").build(); //定義觸發器 Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger_1", "group_1") .startNow().withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5)).build(); scheduler.scheduleJob(jobDetail, trigger); //開啓定時任務 scheduler.start(); } }
【使用案例2】: [建立job類,使用CronSchedulerBuilder]: import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; public class SecondJob implements Job{ public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("使用crontrigger...."); } } [建立測試類]: import org.quartz.CronScheduleBuilder; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.Trigger; import org.quartz.TriggerBuilder; import org.quartz.impl.StdSchedulerFactory; import job.SecondJob; public class SecondScheduler { public static void main(String[] args) throws Exception { //建立一個定時器對象 Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); //建立一個jobDetail對象 JobDetail jobDetail = JobBuilder.newJob(SecondJob.class).withIdentity("job_2", "group_2").build(); //建立一trigger Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger_2", "group_2") .startNow().withSchedule(CronScheduleBuilder.cronSchedule("0 17 1 * * ?")).build(); scheduler.scheduleJob(jobDetail,trigger); scheduler.start(); } }
經過以上案例,能夠了解到quart的使用和簡單入門操做。
固然,做爲當前頗具生命力的開源框架,Quartz 已經獲得了普遍的應用。Quartz 的強大功能和應用靈活性,在企業應用中發揮了巨大的做用。本文描述瞭如何應用 Quartz 開發應用程序,並對企業應用中常見的問題及解決方案進行了討論。