【定时任务】Quartz用法详解
Quartz是一個完全由Java編寫的開源作業調度框架,為在Java應用程序中進行作業調度提供了簡單卻強大的機制。Quartz允許開發人員根據時間間隔來調度作業。它實現了作業和觸發器的多對多的關系,還能把多個作業與不同的觸發器關聯。
quartz核心概念
Job:是一個接口,表示一個工作,要執行的具體內容。只有一個方法void execute(JobExecutionContext context),開發者實現該接口定義運行任務,JobExecutionContext類提供了調度上下文的各種信息。Job運行時的信息保存在JobDataMap實例中;
JobDetail:JobDetail表示一個具體的可執行的調度程序,Job是這個可執行程調度程序所要執行的內容,另外JobDetail還包含了這個任務調度的方案和策略。Quartz在每次執行Job時,都重新創建一個Job實例,所以它不直接接受一個Job的實例,相反它接收一個Job實現類,以便運行時通過newInstance()的反射機制實例化Job。因此需要通過一個類來描述Job的實現類及其它相關的靜態信息,如Job名字、描述、關聯監聽器等信息,JobDetail承擔了這一角色。
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進行定點排除。
Scheduler:代表一個Quartz的獨立運行容器,Trigger和JobDetail可以注冊到Scheduler中,兩者在Scheduler中擁有各自的組及名稱,組及名稱是Scheduler查找定位容器中某一對象的依據,Trigger的組及名稱必須唯一,JobDetail的組和名稱也必須唯一(但可以和Trigger的組和名稱相同,因為它們是不同類型的)。Scheduler定義了多個接口方法,允許外部通過組及名稱訪問和控制容器中Trigger和JobDetail。
ThreadPool:Scheduler使用一個線程池作為任務運行的基礎設施,任務通過共享線程池中的線程提高運行效率。
Quartz的工作原理:
1、scheduler是一個計劃調度器容器(總部),容器里面可以盛放眾多的JobDetail和trigger,當容器啟動后,里面的每個JobDetail都會根據trigger按部就班自動去執行。
2、JobDetail是一個可執行的工作,它本身可能是有狀態的。
3、Trigger代表一個調度參數的配置,什么時候去調。
4、當JobDetail和Trigger在scheduler容器上注冊后,形成了裝配好的作業(JobDetail和Trigger所組成的一對兒),就可以伴隨容器啟動而調度執行了。
5、scheduler是個容器,容器中有一個線程池,用來并行調度執行每個作業,這樣可以提高容器效率。
總結起來就是,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實例。
Quartz的兩大觸發器
Quartz有兩大觸發器,SimpleTrigger和CronTrigger。當且僅需觸發一次或者以固定時間間隔周期觸發執行時使用SimpleTrigger觸發器,需要定時調度任務時使用CronTrigger。
SimpleTrigger:當需要在規定的時間執行一次或在規定的時間段以一定的時間間隔重復觸發執行Job時,SimpleTrigger就可以滿足要求;SimpleTrigger的屬性有:開始時間、結束時間、重復次數和重復的時間間隔,重復次數屬性的值可以為0、正整數、或常量 SimpleTrigger.REPEAT_INDEFINITELY,重復的時間間隔屬性值必須為0或長整型的正整數,以毫秒作為時間單位,當重復的時 間間隔為0時,意味著與Trigger同時觸發執行(或幾乎與Scheduler開始時同時觸發執行)。如果有指定結束時間屬性值,則結束時間屬性優先于重復次數屬性,這樣的好處在于:當我們需要創建一個每間隔10秒鐘觸發一次直到指定的結束時間的 Trigger,而無需去計算從開始到結束的所重復的次數,我們只需簡單的指定結束時間和使用REPEAT_INDEFINITELY作為重復次數的屬性 值即可(我們也可以指定一個比在指定結束時間到達時實際執行次數大的重復次數)。
CronTrigger:支持比 SimpleTrigger 更具體的調度,而且也不是很復雜?;?cron 表達式,CronTrigger 支持類似日歷的重復間隔,而不是單一的時間間隔。Cron表達式Cron Expression參看本人以下博客:http://blog.csdn.net/lmb55/article/details/51013044
兩種調度方式的簡單使用:
TestQuartzJob.java
import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import java.util.Date; /** * 一個簡單的任務,say hello word */ public class TestQuartzJob implements Job { public TestQuartzJob() { } public void execute(JobExecutionContext context)throws JobExecutionException { System.out.println("Hello World! - " + new Date());} }TestQuartzScheduling.java
import java.util.Date; import org.quartz.CronTrigger; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.SimpleTrigger; import org.quartz.impl.StdSchedulerFactory; import org.simpleproxy.Quartz.TestQuartzJob;public class TestQuartzScheduling {/*** 使用SimpleTrigger間隔調度任務* @throws Exception*/public void simpleRun() throws Exception { //1、創建JobDetial對象 JobDetail jobDetail = new JobDetail(); //設置工作項 jobDetail.setJobClass(TestQuartzJob.class); jobDetail.setName("MyJob_1"); jobDetail.setGroup("JobGroup_1"); // JobDetail jobDetail = new JobDetail("MyJob_1","JobGroup_1",TestQuartzJob.class); //2、創建Trigger對象 SimpleTriggerSimpleTrigger strigger = new SimpleTrigger(); strigger.setName("Trigger_1"); strigger.setGroup("Trigger_Group_1"); strigger.setStartTime(new Date()); //設置重復停止時間,并銷毀該Trigger對象 java.util.Calendar c = java.util.Calendar.getInstance(); c.setTimeInMillis(System.currentTimeMillis() + 1000 * 1L); strigger.setEndTime(c.getTime()); strigger.setFireInstanceId("Trigger_1_id_001"); //設置重復間隔時間 // strigger.setRepeatInterval(100 * 1L); // strigger.setRepeatInterval(500 * 1L);strigger.setRepeatInterval(1000 * 1L); //設置重復執行次數 strigger.setRepeatCount(3); //3、創建Scheduler對象,并配置JobDetail和Trigger對象 SchedulerFactory sf = new StdSchedulerFactory(); Scheduler scheduler = null; try { scheduler = sf.getScheduler(); scheduler.scheduleJob(jobDetail, strigger); //4、并執行啟動、關閉等操作 scheduler.start(); // scheduler.shutdown(true); //關閉調度器 } catch (SchedulerException e) { e.printStackTrace(); } } /*** 使用CronTrigger定時調度任務* @throws Exception* @author Administrator* @date 2017-9-6*/public void cronRun() throws Exception { //創建Scheduler對象,并配置JobDetail和Trigger對象 SchedulerFactory schedulerFactory = new StdSchedulerFactory();Scheduler scheduler = schedulerFactory.getScheduler();//創建JobDetial對象 JobDetail jobDetail = new JobDetail("testQuartzJob",Scheduler.DEFAULT_GROUP, TestQuartzJob.class);String cronExpression = "30/5 * * * * ?"; // 每分鐘的30s起,每5s觸發任務 //創建Trigger對象CronTriggerCronTrigger cronTrigger = new CronTrigger("cronTrigger",Scheduler.DEFAULT_GROUP, cronExpression);scheduler.scheduleJob(jobDetail, cronTrigger);scheduler.start();} public static void main(String[] args) throws Exception { TestQuartzScheduling example = new TestQuartzScheduling(); example.simpleRun();example.cronRun();}}運行結果:
在使用SimpleTrigger間隔調度任務的時候,我設置了幾個不同的重復間隔時間,運行得到了不同的結果。
注意:本文示例使用的Quartz版本是1.8.6。
稍后本人會根據源碼,來學習一下Quartz的原理,有興趣的同學,可以先參看下面的幾篇分析文章:
Quartz原理解析:
http://blog.csdn.net/guolong1983811/article/details/51501346
http://lavasoft.blog.51cto.com/62575/181907/
總結
以上是生活随笔為你收集整理的【定时任务】Quartz用法详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Spring学习】spring定时任务
- 下一篇: 【定时任务】JDK java.util.