Quartz[kwɔːts]:石英,其框架和名字同樣簡單樸素又不失魅力,在Java程序界,Quartz大名鼎鼎,不少Java應用幾乎都集成或構建了一個定時任務調度系統,Quartz是一個定時任務調度框架(Quartz官網:http://www.quartz-scheduler.org/)。這個工具java
在美團中的有大量使用,詳見他們的官方博客:http://tech.meituan.com/ 。Quartz是一個很輕量級的java庫,幾乎包含了全部定時的功能。主要接口是Schedule,提供了一些簡單的操做:安排任務或取消任務,啓動或者中止任務。若是你想在應用中使用Quartz,spring
應該實現Job接口,包含了一個execute()方法。若是你想在一個任務執行時間到了的時候通知你,組件應該實現TriggerListener 或者JobListener 接口。Quartz任務能夠在你的應用中啓動和執行,能夠做爲一個獨立的應用程序(經過RMI接口[即Remote Method微信
Invoke 遠程方法調用]),也但是在一個J2EE應用中執行。mybatis
1. 何爲定時任務調度框架?多線程
簡而言之,它能夠領會咱們的意圖在將來某個時刻作咱們想要作的事情,好比,每個月月末的財務報表給財務部門,定時給領導發個郵件短信等等。這時候咱們就須要用到任務調度框架Quartz了。其不只簡單易使用,而且能夠與spring集成(這纔是重點哦!就目前而併發
言,一個Java項目其基礎框架不外乎SSH(struts2+spring+hibernate)、SSM(springMVC+spring+mybatis)。固然,也有一些團隊喜歡springMVC+spring+hibernate這樣搭建。不過,不管是那種搭配spring幾乎是不可或缺的)。任務調度自己涉及到多線程框架
併發、運行時間規則制定和解析、場景保持與恢復、線程池維護等諸多方面的工做。若是直接使用自定義線程這種刀耕火種的原始辦法,開發任務調度程序是一項頗具挑戰性的工做。Java開源的好處就是:領域問題都能找到現成的解決方案(因此圈裏也流行這麼一句:工具
天上飛的理念,必有落地的產品)。 學習
但任務調度除以時間爲關注點外,還應考慮資源的分配。大多數系統都要對資源使用進行控制:服務線程的最大數目必須限額;考慮使用線程池以便共享服務的線程資源、下降頻繁建立、銷燬線程的消耗。spa
2. Quartz是什麼?
Quartz是一個任務調度框架(庫),它幾乎能夠集成到任何應用系統中。術語」job schedule」彷佛爲不一樣的人提供了不一樣的想法。總之,做業調度是負責執行(或通知)其餘軟件組件在預約時間執行的服務組件。雖然經過schedule能夠簡單實現一些系統任務定時執
行,當您學習如何使用它來驅動應用程序的業務流程的流程時,Quartz的所有潛力是能夠實現的。
3. Quartz的一些特色
1)很是靈活的,幷包含多個使用範例,它們能夠單獨或一塊兒使用,以實現您所指望的行爲,並使您可以以最「天然」的方式來編寫您的項目的代碼。
2)很是輕量級的,只須要很是少的配置 —— 它實際上能夠被跳出框架來使用,若是你的需求是一些相對基本的簡單的需求的話。
3)具備容錯機制,而且能夠在重啓服務的時候持久化你的定時任務,你的任務也不會丟失。
4)不是一個任務隊列——雖然它確實能夠在一些小規模應用中合理的做爲一個任務隊列來使用。
5)不是一個網格計算引擎——雖然在某些小規模應用中,這樣作確實能夠達到應用的要求(定時計算、統計一些數據)。
6)不是一個提供給業務人員的執行服務——它是一個庫,很容易集成到應用程序中去作一些將來某時刻可能會一直循環執行的相關的任務。
4. 綜觀目前的 Web 應用,多數應用都具有任務調度的功能。幾種任務調度的 Java 實現方法,包括 Timer,Scheduler, Quartz 以及 JCron Tab等等,其優缺點進行比較,本文不作重點介紹。若有興趣能夠參考如下文章(Spring提供的三種定時任務機制及其比
較 :http://blog.csdn.net/52rainbow/article/details/4004206 ;Flux scheduler:https://flux.ly/ ;三種定時任務的比較:http://blog.csdn.net/liu1pan2min3/article/details/51540470)
5. Quartz 基礎結構
Quartz 對任務調度的領域問題進行了高度抽象,提出了調度器、任務和觸發器 3 個核心概念,並在 org.quartz 中經過接口和類對核心概念進行描述。
Job:接口。開發者經過實現該接口定義須要執行的任務。
JobDetail:Quartz 在每次執行 Job 時,都從新建立一個 Job 實例,因此它不是直接接受一個 Job 的實例,而是接受一個 Job 實現類,以便運行時經過反射機制實例化 Job。所以須要一個類來描述 Job 的實現類及其餘相關的靜態信息,如 Job 名稱、描述、關聯
的監聽器等,JobDetail 承擔了這一角色。
Trigger:描述觸發 Job 執行的時間觸發規則。主要有 SimpleTrigger、CronTrigger 兩個實現類。
SimpleTrigger:當僅須要觸發一次或者以固定間隔週期執行時。
CronTrigger:能夠經過 Cron 表達式定義出各類複雜的調度方案。
Calendar:一些日曆特定時間點的集合(能夠簡單的理解爲 java.util.Calendar 的集合:java.util.Calendar )。一個 Trigger 能夠和多個 Calendar 關聯,以便包含或排除某些時間點。
Scheduler:一個 Quartz 的獨立運行容器,Trigger 和 JobDetail 能夠註冊到 Scheduler 中,二者在 Scheduler 中擁有各自的組及名稱。組及名稱是 Scheduler 查找容器中某一對象的依據,Trigger 和 JobDetail 的組及名稱的組合都必須惟一(但 Scheduler
和 Trigger 的組合名稱能夠相同,由於他們是不一樣的類型,處於不一樣的容器中)。Scheduler 能夠將 Trigger 綁定到某一個 JobDetails 中,這樣當 Trigger 被觸發時,對應的 Job 就被執行。一個 Job 能夠對應多個 Trigger,但一個 Trigger 只能對應一個 Job。
6. 使用 SimpleTrigger
步驟:
實現 Job 接口,可以使 Java 類變爲可調度的任務;
建立描述 Job 的 JobDetail 對象;
建立 SimpleTrigger 對象;
設置觸發 Job 執行的時間規則;
經過 SchedulerFactory 獲取 Scheduler 對象;
向 SchedulerFactory 中註冊 JobDetail 和 Trigger;
啓動調度任務。
7. 使用 CronTrigger
CronTriggr 可以提供比 SimpleTrigger 更有具體實際意義的調度方案,調度規則基於 Cron 表達式,CronTrigger 支持日曆相關的重複時間間隔(例如:每個月第一個週一執行),而不是簡單的週期時間間隔。
8. Cron 表達式
Quartz 使用相似於 Linux 下的 Cron 表達式定義時間規則,Cron 表達式由 6 或 7 個空格分隔的時間字段組成。
Cron 表達式對特殊字符的大小寫不敏感.
9. Cron 表達式中的特殊字符
*:可用於全部字段,表示對應時間域的每個時刻。例如:* 在分鐘字段時,表示 每分鐘
?:只能用在日期和星期字段中,表示一個毫無心義的值,至關於佔位符
-:表示一個範圍。例如:在小時字段中使用 10-12,表示從 10 點到 12 點。即 10,11, 12
,:表示一個列表值。例如:在星期字段中使用 MON,WED,FRI,表示星期一,星期三,星期五
/:x/y 表示一個等步長序列,x 爲起始值,y 爲增量步長。例如:在分鐘字段中使用 0/15,則表示爲 0,15,30 和 45 秒;而 5/15 在分鐘字段表示 5,20,35,50 。*/y 等同於 0/y
L:該字符只在日期和星期字段中使用,表明 Last。
L 用在日期字段中,表明這個月的最後一天
L 用在星期字段中,表明星期六
若 L 出如今星期字段裏,且前面有一個數值 X,則表示 這個月的最後星期 X,例如 6L 表示該月的最後一個星期五
W:該字符只能出如今日期字段裏,是對前導日期的修飾,表示離該日期最近的工做日。例如:15W 表示離該月 15 號最近的工做日:若 15 號是星期六,則匹配 14 號;若 15 號是星期日,則匹配 16 號;若 15 號是星期二,則匹配 15 號。
注意1:關聯的匹配日期不能跨月。例如用戶指定 1W,若 1 號是星期六,則匹配 3 號。
注意2:W 字符串只能指定單一日期,而不能指定日期範圍。
LW:在日期字段能夠組合使用 LW,意爲當月的最後一個工做日
#:只能在星期字段中使用,表示當月某個工做日。例如:6#3 表示當月的第三個星期五(6表示星期五,#3表示當月的第三個),4#5 表示當月的第五個星期三,若沒有第五個星期三,則忽略不觸發
C:該字符只在日期和星期字段中使用,表明 Calendar。意爲計劃所關聯的日期,若是日期沒有被關聯,則至關於日曆中全部日期。例如:5C 在日期字段中就至關於 5 日之後的第一天。1C 在星期字段中至關於星期往後的第一天。
10. Cron 表達式示例
0 0 12 * * ?:天天中午12點觸發
0 15 10 ? * *:天天上午10:15觸發
0 15 10 * ? *: 天天上午10:15觸發
0 15 10 * * ?: 天天上午10:15觸發
0 15 10 * * ? 2005: 2005年的天天上午10:15觸發
0 * 14 * * ?:在天天下午2點到下午2:59期間的每1分鐘觸發
0 0/5 14 * * ?:在天天下午2點到下午2:55期間的每5分鐘觸發
0 0/5 14, 18 * * ?:在天天下午2點到2:55期間和下午6點到6:55期間的每5分鐘,觸發
0 0-5 14 * * ?:在天天下午2點到下午2:05期間的每1分鐘觸發
0 10,44 14 ? 3 WED:每一年三月的星期三的下午2:10和2:44觸發
0 15 10 ? * MON-FRI:週一至週五的上午10:15 觸發
0 15 10 15 * ?:每個月15日上午10:15 觸發
0 15 10 L * ?:每個月最後一日的上午10:15 觸發
0 15 10 ? * 6L:每個月的最後一個星期五上午10:15 觸發
0 15 10 ? * 6L 2002-2005:2002年至2005年的每個月的最後一個星期五上午10:15觸發
0 15 10 ? * 6#3:每個月的第三個星期五上午10:15觸發
11. 在 Spring 中使用 Quartz
Spring 進一步下降了使用 Quartz 的難度:
爲建立 Quartz 的 Scheduler、Trigger 和 JobDetail 提供了便利的 FactoryBean 類,以便可以在 Spring 容器中享受注入.
在 Spring 中配置 JobDetail :
Spring 提供了一個 MethodInvokingJobDetailFactoryBean, 經過這個 FactoryBean 能夠將 Spring 容器中 Bean 的方法包裝成 Quartz 任務,這樣就沒必要爲 Job 建立對應的類了.
12. 在 Spring 中配置 CronTrigger
Spring 爲 CronTrigger 提供了更具 Bean 風格的 CronTriggerFactoryBean.
13. 在 Spring 中配置 Secheduler
Spring 提供了 SchedulerFactoryBean,這個 Bean 擁有以下功能:
以更具備 Bean 風格的方式爲 Scheduler 提供配置信息。
讓 Scheduler 和 Spring IOC 容器的生命週期創建關聯:IOC 容器啓動後,Secheduler 開始工做,IOC 容器關閉前,自動關閉 Scheduler。
startupDelay 屬性:在 SchedulerFactoryBean 初始化完成後,延遲多少秒啓動 Scheduler,默認爲 0,即當即啓動。通常狀況下,能夠經過設置該屬性使 Scheduler 延遲一小段時間後啓動,以便讓 Spring 可以更快初始化容器中的其它 Bean。
quartzPorperties屬性:類型爲 Properties,容許在 Spring 中定義 Quartz 的屬性。其值將覆蓋 quartz.properties 配置文件中的配置。
<!-- Start -->
本文只是Quartz的一個入門,接下來我會逐步推出Quartz的高級用法和在實際項目中的Demo。獲知及時信息,請關注個人我的微信訂閱號:0與1的那點事
<!-- End -->
本文爲博主原創文章,轉載請註明出處!
http://www.cnblogs.com/libingbin/
感謝您的閱讀。