Java定時任務排程詳解
前言
在實際專案開發中,除了Web應用、SOA服務外,還有一類不可缺少的,那就是定時任務排程。定時任務的場景可以說非常廣泛,比如某些視訊網站,購買會員後,每天會給會員送成長值,每月會給會員送一些電影券;比如在保證最終一致性的場景中,往往利用定時任務排程進行一些比對工作;比如一些定時需要生成的報表、郵件;比如一些需要定時清理資料的任務等。本篇部落格將系統的介紹定時任務排程,會涵蓋Timer、ScheduledExecutorService、開源工具包Quartz,以及Spring和Quartz的結合等內容。
JDK原生定時工具:Timer
定時任務排程:基於給定的時間點、給定的時間間隔、給定的執行次數自動執行的任務。
Timer位於java.util包下,其內部包含且僅包含一個後臺執行緒(TimeThread)對多個業務任務(TimeTask)進行定時定頻率的排程。
schedule的四種用法和scheduleAtFixedRate的兩種用法
引數說明:
task:所要執行的任務,需要extends TimeTask override run()
time/firstTime:首次執行任務的時間
period:週期性執行Task的時間間隔,單位是毫秒
delay:執行task任務前的延時時間,單位是毫秒
很顯然,通過上述的描述,我們可以實現:
延遲多久後執行一次任務;指定時間執行一次任務;延遲一段時間,並週期性執行任務;指定時間,並週期性執行任務;
思考1:如果time/firstTime指定的時間,在當前時間之前,會發生什麼呢?
在時間等於或者超過time/firstTime的時候,會執行task!也就是說,如果time/firstTime指定的時間在當前時間之前,就會立即得到執行。
思考2:schedule和scheduleAtFixedRate有什麼區別?
scheduleAtFixedRate:每次執行時間為上一次任務開始起向後推一個period間隔,也就是說下次執行時間相對於上一次任務開始的時間點,因此執行時間不會延後,但是存在任務併發執行的問題。
schedule:每次執行時間為上一次任務結束後推一個period間隔,也就是說下次執行時間相對於上一次任務結束的時間點,因此執行時間會不斷延後。
思考3:如果執行task發生異常,是否會影響其他task的定時排程?
如果TimeTask丟擲RuntimeException,那麼Timer會停止所有任務的執行!
思考4:Timer的一些缺陷?
前面已經提及到Timer背後是一個單執行緒,因此Timer存在管理併發任務的缺陷:所有任務都是由同一個執行緒來排程,所有任務都是序列執行,意味著同一時間只能有一個任務得到執行,而前一個任務的延遲或者異常會影響到之後的任務。
其次,Timer的一些排程方式還算比較簡單,無法適應實際專案中任務定時排程的複雜度。
一個簡單的Demo例項
Timer其他需要關注的方法
cancel():終止Timer計時器,丟棄所有當前已安排的任務(TimeTask也存在cancel()方法,不過終止的是TimeTask)
purge():從計時器的任務佇列中移除已取消的任務,並返回個數
JDK對定時任務排程的執行緒池支援:ScheduledExecutorService
由於Timer存在的問題,JDK5之後便提供了基於執行緒池的定時任務排程:ScheduledExecutorService。
設計理念:每一個被排程的任務都會被執行緒池中的一個執行緒去執行,因此任務可以併發執行,而且相互之間不受影響。
我們直接看例子:
執行結果:
定時任務大哥:Quartz
雖然ScheduledExecutorService對Timer進行了執行緒池的改進,但是依然無法滿足複雜的定時任務排程場景。因此OpenSymphony提供了強大的開源任務排程框架:Quartz。Quartz是純Java實現,而且作為Spring的預設排程框架,由於Quartz的強大的排程功能、靈活的使用方式、還具有分散式叢集能力,可以說Quartz出馬,可以搞定一切定時任務排程!
Quartz的體系結構
先來看一個Demo:
說明:
1、從程式碼上來看,有XxxBuilder、XxxFactory,說明Quartz用到了Builder、Factory模式,還有非常易懂的鏈式程式設計風格。
2、Quartz有3個核心概念:排程器(Scheduler)、任務(Job&JobDetail)、觸發器(Trigger)。(一個任務可以被多個觸發器觸發,一個觸發器只能觸發一個任務)
3、注意當Scheduler排程Job時,實際上會通過反射newInstance一個新的Job例項(待排程完畢後銷燬掉),同時會把JobExecutionContext傳遞給Job的execute方法,Job例項通過JobExecutionContext訪問到Quartz執行時的環境以及Job本身的明細資料。
4、JobDataMap可以裝載任何可以序列化的資料,存取很方便。需要注意的是JobDetail和Trigger都可以各自關聯上JobDataMap。JobDataMap除了可以通過上述程式碼獲取外,還可以在YourJob實現類中,新增相應setter方法獲取。
5、Trigger用來告訴Quartz排程程式什麼時候執行,常用的觸發器有2種:SimpleTrigger(類似於Timer)、CronTrigger(類似於Linux的Crontab)。
6、實際上,Quartz在進行排程器初始化的時候,會載入quartz.properties檔案進行一些屬性的設定,比如Quartz後臺執行緒池的屬性(threadCount)、作業儲存設定等。它會先從工程中找,如果找不到那麼就是用quartz.jar中的預設的quartz.properties檔案。
7、Quartz存在監聽器的概念,比如任務執行前後、任務的新增等,可以方便實現任務的監控。
CronTrigger示例
Cron表示式的寫法
這裡給出一些常用的示例:
0 15 10 * * ? * 每天10點15分觸發
0 15 10 * * ? 2017 2017年每天10點15分觸發
0 * 14 * * ? 每天下午的 2點到2點59分每分觸發
0 0/5 14 * * ? 每天下午的 2點到2點59分(整點開始,每隔5分觸發)
0 0/5 14,18 * * ? 每天下午的 2點到2點59分、18點到18點59分(整點開始,每隔5分觸發)
0 0-5 14 * * ? 每天下午的 2點到2點05分每分觸發
0 15 10 ? * 6L 每月最後一週的星期五的10點15分觸發
0 15 10 ? * 6#3 每月的第三週的星期五開始觸發
我們可以通過一些Cron線上工具非常方便的生成,比如http://www.pppet.net/等。
Spring和Quartz的整合
實際上,Quartz和Spring結合是很方便的,無非就是進行一些配置。大概基於2種方式:
第一,普通的類,普通的方法,直接在配置中指定(MethodInvokingJobDetailFactoryBean)。
第二,需要繼承QuartzJobBean,複寫指定方法(executeInternal)即可。
然後,就是一些觸發器、排程器的配置了,這裡不再展開介紹了,只要弄懂了原生的Quartz的使用,那麼和Spring的結合使用就會很簡單。
好了,到這裡,定時任務排程就結束了,週末愉快!
2017-09-24 張豐哲
相關文章
- 使用Java實現定時任務排程Java
- Linux 定時任務排程Linux
- laravel框架任務排程(定時執行任務)Laravel框架
- Crontab定時任務排程介紹
- Android 中的定時任務排程Android
- Spring排程定時任務的方式Spring
- Oracle 定時任務詳解Oracle
- 定時任務crontab 詳解
- 利用排程任務定時刪除分割槽
- 深入 Java Timer 定時任務排程器實現原理Java
- 詳解 MySQL 用事件排程器 Event Scheduler 建立定時任務MySql事件
- 詳解MySQL用事件排程器Event Scheduler建立定時任務MySql事件
- 詳解BI系統中的任務排程
- 基於Azkaban的任務定時排程實踐
- NET作業排程(定時任務)-Quartz.Netquartz
- Crontab 定時任務命令詳解
- 任務排程
- 一文詳解 Linux Crontab 排程任務Linux
- Java定時任務解決方案Java
- Java 分散式任務排程平臺:PowerJob 快速開始+配置詳解Java分散式
- 定時任務@Scheduled引數詳解
- Java 定時任務Java
- 用海豚排程器定時排程從Kafka到HDFS的kettle任務指令碼Kafka指令碼
- 『學了就忘』Linux系統定時任務 — 89、任務排程工具anacronLinux
- 定時排程系列之Quartz.Net詳解quartz
- Laravel 任務排程Laravel
- Airflow 任務排程AI
- Quartz定時任務框架(二) Quartz詳解quartz框架
- Linux/UNIX 定時任務 cron 詳解Linux
- Oracle定時任務(DBMS_Job)詳解Oracle
- Linux Crontab 定時任務 命令詳解Linux
- java web定時任務JavaWeb
- Java & Go 定時任務JavaGo
- 深入解讀Quartz任務排程器quartz
- [原始碼分析] 定時任務排程框架 Quartz 之 故障切換原始碼框架quartz
- 在Spring中使用JDK定時器實現排程任務SpringJDK定時器
- Spark中資源排程和任務排程Spark
- 定時任務報警通知解決方案詳解