Quartz 是個開源的做業調度框架,爲在 Java 應用程序中進行做業調度提供了簡單卻強大的機制。Quartz 容許開發人員根據時間間隔(或天)來調度做業。它實現了做業和觸發器的多對多關係,還能把多個做業與不一樣的觸發器關聯。整合了 Quartz 的應用程序能夠重用來自不一樣事件的做業,還能夠爲一個事件組合多個做業。java
SimpleTrigger 當須要在規定的時間執行一次或在規定的時間段以必定的時間間隔重複觸發執行Job時,SimpleTrigger就能夠知足要求;SimpleTrigger的屬性有:開始時間、結束時間、重複次數和重複的時間間隔,重複次數屬性的值能夠爲0、正整數、或常量 SimpleTrigger.REPEAT_INDEFINITELY,重複的時間間隔屬性值必須爲0或長整型的正整數,以毫秒做爲時間單位,當重複的時 間間隔爲0時,意味着與Trigger同時觸發執行(或幾乎與Scheduler開始時同時觸發執行)。若是有指定結束時間屬性值,則結束時間屬性優先於重複次數屬性,這樣的好處在於:當咱們須要建立一個每間隔10秒鐘觸發一次直到指定的結束時間的 Trigger,而無需去計算從開始到結束的所重複的次數,咱們只需簡單的指定結束時間和使用REPEAT_INDEFINITELY做爲重複次數的屬性 值便可(咱們也能夠指定一個比在指定結束時間到達時實際執行次數大的重複次數)。spring
CronTrigger 支持比 SimpleTrigger 更具體的調度,並且也不是很複雜。基於 cron 表達式,CronTrigger 支持相似日曆的重複間隔,而不是單一的時間間隔。併發
Cron 表達式包括如下 7 個字段:app
格式: [秒] [分] [小時] [日] [月] [周] [年]
序號 說明 是否必填 容許填寫的值 容許的通配符
1 秒 是 0-59 , - * /
2 分 是 0-59 , - * /
3 小時 是 0-23 , - * /
4 日 是 1-31 , - * ? / L W
5 月 是 1-12 or JAN-DEC , - * /
6 周 是 1-7 or SUN-SAT , - * ? / L #
7 年 否 empty 或 1970-2099 , - * /框架
Quartz官方網站對SimpleTrigger和CronTrigger的簡單對比:
SimpleTrigger is handy if you need 'one-shot' execution (just single execution of a job at a given moment in time), or if you need to fire a job at a given time, and have it repeat N times, with a delay of T between executions.當你須要的是一次性的調度(僅是安排單獨的任務在指定的時間及時執行),或者你須要在指定的時間激活某個任務並執行N次,設置每次任務執行的間隔時間T。那此時使用SimpleTrigger將是很是方便的。 ide
CronTrigger is useful if you wish to have triggering based on calendar-like schedules - such as "every Friday, at noon" or "at 10:15 on the 10th day of every month."若是你須要安排的任務時基於日期的-好比"每一個星期五正午"或者"每月10號的10:15",使用CronTrigger將是很是有用的。優化
<!-- cronTrigger實現方式 --> <bean name="exampleJob" class="org.springframework.scheduling.quartz.JobDetailBean"> <property name="jobClass" value="com.ouku.entities.report.ReportTimerTask" /> <property name="jobDataAsMap"> <map> <entry key="timeout" value="3600" /> </map> </property> </bean> <bean id="springUtil" class="com.ouku.util.SpringUtil" /> <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="exampleJob" /> <!-- run every morning at 6 AM --> <!-- <property name="cronExpression" value="0 0 6 * * ?" /> --> <!-- <property name="cronExpression" value="0 0/1 * * * ?" /> --><!-- 每分鐘 --> <property name="cronExpression" value="0/5 * * * * ?" /> <!-- 每秒 --> </bean> <bean id="exampleBusinessObject" class="com.ouku.entities.report.ReportTimerTaskTwo" /> <bean id="jobDetail" <!-- simpleTrigger實現方式 --> class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="exampleBusinessObject" /> <property name="targetMethod" value="doIt" /> <property name="concurrent" value="false" /> </bean> <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"> <!-- see the example of method invoking job above --> <property name="jobDetail" ref="jobDetail" /> <!-- 0 seconds --> <property name="startDelay" value="0" /> <!-- repeat every 5 seconds --> <property name="repeatInterval" value="5000" /> </bean> <!-- 總調度用於啓動Spring定時器 --> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="cronTrigger" /> <ref bean="simpleTrigger"/> </list> </property> </bean>
其中<property name="concurrent" value="false" />網站
package com.ouku.entities.report; import java.util.Date; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; import com.ouku.report.ReportTask; public class ReportTimerTask extends QuartzJobBean { private int timeout; public void setTimeout(int timeout) { this.timeout = timeout; } @Override protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException { try { Date date = new Date(); String dd = " " + date.getMinutes() + ":" + date.getSeconds() + " "; System.out.println("AAA" + dd); //to do } catch (Exception e) { e.printStackTrace(); } } }
package com.ouku.entities.report; import java.util.Date; import org.quartz.JobExecutionException; import com.ouku.report.ReportTask; public class ReportTimerTaskTwo { public void doIt() throws JobExecutionException { try { Date date = new Date(); String dd = " " + date.getMinutes() + ":" + date.getSeconds() + " "; System.out.println("sss1" + dd); //to do .. } catch (Exception e) { e.printStackTrace(); } } }
在使用併發的狀況下,當Job執行時間超過間隔時間時,調度框架爲了能讓任務按照咱們預約的時間間隔執行,會立刻啓用新的線程執行任務。this
再次強調,spring4 quartz最多能夠爲咱們開啓十個線程,當咱們須要執行的任務有鎖的狀況下,那麼在十個線程用完以後,定時器沒有線程能夠開啓,這時候就會出現定時任務的時間間隔超過咱們設定的時間間隔;spa
咱們怎麼解決這個狀況呢?
1、優化咱們執行的job,使其在設定的時間間隔內執行完;
2、設置時間間隔更長一點;
咱們再來看看串行執行和併發執行的區別:
下面是串行執行時,每一個線程的執行狀況:
咱們能夠看到,每一個定時任務是在job完成以後纔會開啓新的線程來執行下一個job;
下面看看併發執行,每一個線程執行的狀況:
咱們能夠看到,定時任務是按照咱們設置的時間間隔執行的,不會在乎job是否執行完,若是沒有執行完,定時任務會開啓一個新的線程來執行job;