1. 程式人生 > >Quartz定時任務調度機制解析(CronTirgger、SimpleTrigger )

Quartz定時任務調度機制解析(CronTirgger、SimpleTrigger )

sched 它的 main 目前 可選值 -- 實現接口 不能 三種

一、Quartz的介紹

  Quartz 是 OpenSymphony 開源組織在任務調度領域的一個開源項目,完全基於 Java 實現。該項目於 2009 年被 Terracotta 收購,目前是 Terracotta 旗下的一個項目。它是一個而安全有java辨析額的開源作業調度框架。

二、Quartz 具有以下特點

1.強大的調度功能,例如支持豐富多樣的調度方法,可以滿足各種常規及特殊需求;

2.靈活的應用方式,例如支持任務和調度的多種組合方式,支持調度數據的多種存儲方式;

3.分布式和集群能力,Terracotta 收購後在原來功能基礎上作了進一步提升;

4.另外,作為 Spring 默認的調度框架,Quartz 很容易與 Spring 集成實現靈活可配置的調度功能。

開發企業級任務調度應用Quartz 就是啟動定時任務的框架 !!

三、基本開發流程及簡單實例

  利用 Quartz 進行開發相當簡單,只需要將下載開發包中的 quartz-all-1.8.4.jar 加入到 classpath 即可。根據筆者的經驗,對於任務調度功能比較復雜的企業級應用來說,最好在開發階段將 Quartz 的源代碼導入到開發環境中來。一方面可以通過閱讀源碼了解 Quartz 的實現機理,另一方面可以通過擴展或修改 Quartz 的一些類來實現某些 Quartz 尚不提供的功能。

1.Quartz定時調度框架使用說明

1) Job任務

  具體要執行任務的程序。比如發短信,發郵件,訪問數據庫,同步數據,

數據的清洗,本項目中使用在宣傳活動定時過期的模塊。

2)Trigger觸發器

  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-315.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            年(可選的域,可有可無)

        [特殊字符]
            ‘/‘  用來表示增量
            ‘?‘  用來表示沒有執行的值,但是,4、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 開發應用程序,並對企業應用中常見的問題及解決方案進行了討論。

Quartz定時任務調度機制解析(CronTirgger、SimpleTrigger )