初識一個任務調度框架quartz

QUARTZ的官網http://www.quartz-scheduler.org/html

使用前準備,使用Maven導入依賴(Jar包可在官網上下載):java

<dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <version>2.2.1</version>
        </dependency>

1.Quartz的簡單入門

public class MyJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("執行了指定的任務!------" + new SimpleDateFormat("HH:mm:ss").format(new Date()));
    }

    public static void main(String[] args) {
        try {
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            scheduler.start();
            JobDetail job = JobBuilder.newJob(MyJob.class)
                    .withIdentity("job1", "group1")
                    .build();
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("trigger1", "group1")
                    .startNow()
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                            .withIntervalInSeconds(5)
                            .repeatForever())
                    .build();

            scheduler.scheduleJob(job, trigger);
            Thread.sleep(100 * 1000);
            scheduler.shutdown();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

首先必須自定義一個Job,如上的MyJob類並實現org.quartz.Job接口,在重寫的方法裏就是須要定時調用的任務。spring

注意: scheduler.scheduleJob(job, trigger);這條語句執行後該任務並不會被激活,須要在 scheduler.start();這條語句執行後,Scheduler任務纔會執行,這條語句scheduler.shutdown();將會關閉被定時執行的任務。api

以上使用了簡單的Scheduler,如下可使用更加複雜的Scheduler:併發

其中最關鍵的是CroneExpression,它表示該任務執行的時間,每一個時間表示:秒 分鐘 小時 日 月 周 年(可選填)。ide

含義以下:ui

其中特殊字符含義以下:spa

'*' 字符能夠用於全部字段,在「分」字段中設爲"*"表示"每一分鐘"的含義。code

 

'?' 字符能夠用在「日」和「周幾」字段. 它用來指定 '不明確的值'. 這在你須要指定這兩個字段中的某一個值而不是另一個的時候會被用到。在後面的例子中能夠看到其含義。orm

 

'-' 字符被用來指定一個值的範圍,好比在「小時」字段中設爲"10-12"表示"10點到12點".

 

',' 字符指定數個值。好比在「周幾」字段中設爲"MON,WED,FRI"表示"the days Monday, Wednesday, and Friday".

 

'/' 字符用來指定一個值的的增長幅度. 好比在「秒」字段中設置爲"0/15"表示"第0, 15, 30, 和 45秒"。而 "5/15"則表示"第5, 20, 35, 和 50". 在'/'前加"*"字符至關於指定從0秒開始. 每一個字段都有一系列能夠開始或結束的數值。對於「秒」和「分」字段來講,其數值範圍爲0到59,對於「小時」字段來講其爲0到23, 對於「日」字段來講爲0到31, 而對於「月」字段來講爲1到12。"/"字段僅僅只是幫助你在容許的數值範圍內從開始"第n"的值。 所以對於「月」字段來講"7/6"只是表示7月被開啓而不是「每六個月」, 請注意其中微妙的差異。

 

'L'字符可用在「日」和「周幾」這兩個字段。它是"last"的縮寫, 可是在這兩個字段中有不一樣的含義。例如,「日」字段中的"L"表示"一個月中的最後一天" —— 對於一月就是31號對於二月來講就是28號(非閏年)。而在「周幾」字段中, 它簡單的表示"7" or "SAT",可是若是在「周幾」字段中使用時跟在某個數字以後, 它表示"該月最後一個星期×" —— 好比"6L"表示"該月最後一個週五"。當使用'L'選項時,指定肯定的列表或者範圍很是重要,不然你會被結果搞糊塗的。

 

'W' 可用於「日」字段。用來指定歷給定日期最近的工做日(週一到週五) 。好比你將「日」字段設爲"15W",意爲: "離該月15號最近的工做日"。所以若是15號爲週六,觸發器會在14號即週五調用。若是15號爲週日, 觸發器會在16號也就是週一觸發。若是15號爲週二,那麼當天就會觸發。然而若是你將「日」字段設爲"1W", 而一號又是週六, 觸發器會於下週一也就是當月的3號觸發,由於它不會越過當月的值的範圍邊界。'W'字符只能用於「日」字段的值爲單獨的一天而不是一系列值的時候。

 

'L'和'W'能夠組合用於「日」字段表示爲'LW',意爲"該月最後一個工做日"。

 

'#' 字符可用於「周幾」字段。該字符表示「該月第幾個周×」,好比"6#3"表示該月第三個週五( 6表示週五而"#3"該月第三個)。再好比: "2#1" = 表示該月第一個週一而 "4#5" = 該月第五個週三。注意若是你指定"#5"該月沒有第五個「周×」,該月是不會觸發的。

 

'C' 字符可用於「日」和「周幾」字段,它是"calendar"的縮寫。它表示爲基於相關的日曆所計算出的值(若是有的話)。若是沒有關聯的日曆, 那它等同於包含所有日曆。「日」字段值爲"5C"表示"日曆中的第一天或者5號及其之後",「周幾」字段值爲"1C"則表示"日曆中的第一天或者週日及其之後"。

 

對於「月份」字段和「周幾」字段來講合法的字符都不是大小寫敏感的。

更準確的信息請參考官方API文檔:http://www.quartz-scheduler.org/api/2.2.1/index.html

 

2.Quartz與Spring的整合及使用

增長導入Spring的支持包:

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>

首先寫一個任務類:

public class MyTasks {

    public void task1() {
        System.out.println("Quartz與Spring的集成-----" + new SimpleDateFormat("HH:mm:ss").format(new Date()));
    }

    public void task2() {
        System.out.println("這是另外一個任務-----" + new SimpleDateFormat("HH:mm:ss").format(new Date()));
    }
}

Spring的配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
       xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id = "mytask" class = "at.flying.quartz.MyTasks" />
    <!--設置JobDetail-->
    <bean id = "jobDetail1" class = "org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <!--指定要執行的任務的類-->
        <property name = "targetObject" ref = "mytask" />
        <!--指定執行的方法-->
        <property name = "targetMethod" value = "task1" />
        <!--指定任務能否同步執行-->
        <property name = "concurrent" value = "false" />
    </bean>
    <bean id = "jobDetail2" class = "org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <!--指定要執行的任務的類-->
        <property name = "targetObject" ref = "mytask" />
        <!--指定執行的方法-->
        <property name = "targetMethod" value = "task2" />
        <!--指定任務能否同步執行-->
        <property name = "concurrent" value = "false" />
    </bean>

    <!--設置簡單的Trigger-->
    <bean id = "simpleTrigger" class = "org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
        <!--設置jobDetail-->
        <property name = "jobDetail" ref = "jobDetail1" />
        <!--延遲執行的時間,毫秒-->
        <property name = "startDelay" value = "#{10*1000}" />
        <!--每次執行的間隔時間,毫秒-->
        <property name = "repeatInterval" value = "5000" />
        <!--設置重複執行任務的次數,這裏注意設置10次實際上是共執行11次,執行總次數在此基礎上加上1,-->
        <property name = "repeatCount" value = "10" />
    </bean>

    <!--設置複雜的Trigger-->
    <bean id = "cronTrigger" class = "org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <!--設置jobDetail-->
        <property name = "jobDetail" ref = "jobDetail2" />
        <!--設置CronExpression表達式(這裏表示:2016年8月12日15時每分鐘的第20秒)-->
        <property name = "cronExpression" value = "20 * 15 12 8 ? 2016" />
    </bean>

    <!--設置任務調度工廠-->
    <bean id = "scheduler" class = "org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name = "triggers">
            <list>
                <ref bean = "simpleTrigger" />
                <ref bean = "cronTrigger" />
            </list>
        </property>
    </bean>
</beans>

啓動Web就能夠看到任務執行成功。

以上代碼中註釋詳盡就再也不解釋了。

配置文件中的<property name = "concurrent" value = "false" />表示以下意思:

對於相同的JobDetail,當指定多個Trigger時, 極可能第一個job完成以前,第二個job就開始了。指定concurrent設爲false,多個job不會併發運行,第二個job將不會在第一個job完成以前開始,第二個Job將會被延遲執行直到第一個Job執行完畢。concurrent設爲true表示兩個Job執行能夠併發進行。

總結:

咱們能夠看到不管是採用Spring的配置文件配置定時任務,仍是使用純Java代碼配置定時任務,整體的過程大致一致:

1.寫本身的任務類,這裏彷佛採用Spring的集成比較好。若是使用純Java代碼,須要實現org.quartz.Job接口,而且若是須要設置多個任務的話就要寫多個類,每個類只能完成一個任務。可是在Spring中,能夠把多個任務寫成多個方法放在一個Java普通類中,在使用時,只需在Spring配置文件中配置便可。

2.建立JobDetail類。該類的主要做用是指定具體的要執行的任務。

3.建立Trigger類。該類的主要做用是設置執行的任務的執行時間(執行方式)

4.建立Scheduler類。該類的主要做用是管理任務觸發器(Trigger),Trigger的觸發最終由Scheduler發起。

 

簡單觸發器與複雜觸發器的主要點在於:簡單觸發器只支持簡單的執行時間點和執行方式,複雜觸發器可使用規定的CronExpression表達出更加複雜的時間點和執行方式。

更多內容可查看QUARTZ的官網:http://www.quartz-scheduler.org/

相關文章
相關標籤/搜索