quartz的學習和簡單使用
以前在框架中使用過,很多都是純粹的複製貼上,瞭解過用法知道如何配置,但時間久了就沒什麼印象了,現在重新撿起來,再次進行學習。
quartz相關的介紹都已經很多了,我就不重複囉嗦,簡單說一下個人的認識和使用。
* 定時任務 quartz的設計比較合理,將排程Scheduler、觸發Trigger、任務進行分離Job(這裡使用JobDetail建立Job的例項)
* 排程Scheduler負責任務的排程執行以及任務的銷燬
* 觸發器設定Trigger事件的觸發條件或時間,分為SimpleTrigger和CronTrigger兩種常用模式,
* 當然還有其他兩種模式CalendarIntervalTrigger 按日期觸發的Trigger 和 DailyTimeIntervalTrigger 按天觸發的Trigger
* 其中CronTrigger中的設定規範基本等同於cron4j,不過增加了秒
* JobDetail是任務的定義,而Job是任務的執行邏輯
在學習cron4j的時候,我使用了的內部類,在建立quartz的時候我也同樣使用了內部類,但示例始終不能啟動,找了很長時間,沒想到這裡還有個坑,現在也不知道因為什麼。
下面程式碼是個反面教材,是不能執行的,需要將HelloTask類單獨出來寫才可以執行。
import java.util.Date; import org.quartz.Job; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; importorg.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.Trigger; import org.quartz.impl.StdSchedulerFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.quartz.JobBuilder.newJob; import static org.quartz.SimpleScheduleBuilder.simpleSchedule;import static org.quartz.TriggerBuilder.newTrigger; import static org.quartz.DateBuilder.evenMinuteDate ; /** * * @author Uboobo * * 定時任務 quartz的設計比較合理,將排程Scheduler、觸發Trigger、任務進行分離Job(這裡使用JobDetail建立Job的例項) * 排程Scheduler負責任務的排程執行以及任務的銷燬 * 觸發器設定Trigger事件的觸發條件或時間,分為SimpleTrigger和CronTrigger兩種常用模式, * 當然還有其他兩種模式CalendarIntervalTrigger 按日期觸發的Trigger 和 DailyTimeIntervalTrigger 按天觸發的Trigger * 其中CronTrigger中的設定規範基本等同於cron4j,增加了秒 * JobDetail是任務的定義,而Job是任務的執行邏輯 * */ public class QuartzTask { // 建立scheduler public static void createScheduler(JobDetail job, Trigger trigger) { try { // 建立scheduler,需要捕獲排程異常 Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); // 加入這個排程 scheduler.scheduleJob(job, trigger); // 啟動之 scheduler.start(); // 執行一段時間後關閉 Thread.sleep(10000); scheduler.shutdown(true); } catch (SchedulerException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // 建立Trigger public static Trigger createTrigger() { Trigger trigger = newTrigger() .withIdentity("myTrigger", "group1") .startNow() .withSchedule(simpleSchedule() .withIntervalInSeconds(10)//間隔時間是10s .repeatForever()) .build(); return trigger; } // 建立Job public static JobDetail createJob() { JobDetail job = newJob(HelloTask.class) .withIdentity("myJob", "group1") .build(); return job; } // 內部類 ,坑在這這裡,需要使用單獨的類 static class HelloTask implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { JobDetail detail = context.getJobDetail(); // TODO Auto-generated method stub String name = detail.getJobDataMap().getString("name"); System.out.println(" my job do..." + name); } } public static void main(String[] args) throws Exception { JobDetail job = createJob(); Trigger trigger = createTrigger(); createScheduler(job,trigger); }
程式碼裡沒有標註太多註釋,這裡多說幾句,一個quartz任務要執行的話,首先要通過StdSchedulerFactory.getDefaultScheduler() 建立scheduler,只有這樣才能使用排程,然後要通過Trigger去建立一個或多個觸發器並設定執行時間,然後再去使用JobDetail建立job,再使用job去載入我們要去執行的類,最後使用排程去載入執行。
quartz的設計將其進行分層還是有很多好處,但也增加了一些複雜度,如果直接使用scheduler去呼叫job也是可以的,但如果實現多重負責設定就比較困難了。
下面貼一下可以執行的程式碼
public static void main(String [] args) { try { // 建立scheduler Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); // 定義一個Trigger Trigger trigger = newTrigger().withIdentity("trigger1", "group1") // 定義name/group .startNow()// 一旦加入scheduler,立即生效 .withSchedule(simpleSchedule() // 使用SimpleTrigger .withIntervalInSeconds(1) // 每隔一秒執行一次 .repeatForever()) // 一直執行,奔騰到老不停歇 .build(); // 定義一個JobDetail JobDetail job = newJob(HelloJob.class) // 定義Job類為HelloQuartz類,這是真正的執行邏輯所在 .withIdentity("job1", "group1") // 定義name/group .usingJobData("name", "quartz") // 定義屬性 .build(); // 加入這個排程 scheduler.scheduleJob(job, trigger); // 啟動之 scheduler.start(); // 執行一段時間後關閉 Thread.sleep(100000); scheduler.shutdown(true); } catch (Exception e) { e.printStackTrace(); } }
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; /** * hello world Quartz * @author weeks * */ public class HelloJob implements Job { private static Logger _log = LoggerFactory.getLogger(HelloJob.class); /** * Job,Job需要一個公有的建構函式,否則Factory無法構建 */ public HelloJob() { } /** * 實現execute方法 */ public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println(" my job do..."); } }
這裡還遺留一個問題,import中使用了 static 有點不太明白,設計者為什麼要這麼做,這麼做有什麼好處,待我瞭解之後再來補充。