Java之定时任务详解
在我們編程過程中如果需要執行一些簡單的定時任務,無須做復雜的控制,我們可以考慮使用JDK中的Timer定時任務來實現。下面就其原理、實例以及Timer缺陷三個方面來解析java Timer定時器。
在java中一個完整的定時任務需要由Timer,TimerTask兩個類來配合完成。API中是這樣定義它們的,Timer:一種工具,線程用其安排以后在后臺線程中執行的任務。可安排任務執行一次,或者定期重復執行。我們可以這樣理解Timer是一種定時器工具,用來在一個后臺線程計劃執行指定任務,而TimerTask一個抽象類,它的子類代表一個可以被Timer計劃的任務。
Timer類
在工具類Timer中,提供了四個構造方法,每個構造方法都啟動了計時器線程,同時Timer類可以保證多個線程可以共享單個Timer對象而無需進行外部同步,所以Timer類是線程安全的。但是由于每一個Timer對象對應的是單個后臺線程,用于順序執行所有的計時器任務,一般情況下我們的線程任務執行所消耗的時間應該非常短,但是由于特殊情況導致某個定時器任務執行的時間太長,那么他就會“獨占”計時器的任務執行線程,其后的所有線程都必須等待它執行完,這就會延遲后續任務的執行,使這些任務堆積在一起,具體情況我們后面分析。
當程序初始化完成Timer后,定時任務就會按照我們設定的時間去執行,Timer提供了schedule方法,該方法有多中重載方式來適應不同的情況,如下:
schedule(TimerTask task, Date time):安排在指定的時間執行指定的任務。
?
schedule(TimerTask task, Date firstTime, long period) :安排指定的任務在指定的時間開始進行重復的固定延遲執行。
?
schedule(TimerTask task, long delay) :安排在指定延遲后執行指定的任務。
?
schedule(TimerTask task, long delay, long period) :安排指定的任務從指定的延遲后開始進行重復的固定延遲執行。
同時也重載了scheduleAtFixedRate方法,scheduleAtFixedRate方法與schedule相同,只不過他們的側重點不同,區別后面分析。
scheduleAtFixedRate(TimerTask task, Date firstTime, long period):安排指定的任務在指定的時間開始進行重復的固定速率執行。
scheduleAtFixedRate(TimerTask task, long delay, long period):安排指定的任務在指定的延遲后開始進行重復的固定速率執行。
?
TmierTask類
TimerTask類是一個抽象類,由Timer 安排為一次執行或重復執行的任務。它有一個抽象方法run()方法,該方法用于執行相應計時器任務要執行的操作。因此每一個具體的任務類都必須繼承TimerTask,然后重寫run()方法。
另外它還有兩個非抽象的方法:
boolean cancel():取消此計時器任務。
long scheduledExecutionTime():返回此任務最近實際執行的安排執行時間。
2.1.指定延遲時間執行定時任務
---------------------------------------------------------------------------------
--------------------------------------------------------------------------------
運行結果:首先打印:timer begin...3秒后打印:Time's up....
2.2.在指定時間執行定時任務
---------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------
當時間到達19:23:00時就會執行該線程任務,當然大于該時間也會執行!!
運行結果:
設定時間time=Wed Jul 06 19:23:00 CST 2016開始執行任務
正在執行任務....
任務執行完成....
任務完成時間Wed Jul 06 19:23:00 CST 2016
2.3.在指定延遲時間后以指定的間隔時間
---------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
運行結果:
本次執行該線程的時間為:Wed Jul 06 20:09:15 CST 2016
本次執行該線程的時間為:Wed Jul 06 20:09:17 CST 2016
本次執行該線程的時間為:Wed Jul 06 20:09:19 CST 2016
............
對于這個線程任務,如果我們不將該任務停止,他會一直運行下去。
對于上面三個實例,這里只是簡單的演示了一下,同時也沒有講解scheduleAtFixedRate方法的例子,其實該方法與schedule方法一樣!
3.1.Timer的缺陷
Timer計時器可以定時(指定時間執行任務),延遲(延遲5s執行任務),周期性的執行任務(每隔1s執行任務)但是,Timer存在一些缺陷。首先Timer對調度的支持是基于絕對時間的,而不是相對時間,所以它對系統時間的改變非常的敏感。其次Timer線程是不會捕獲異常的,如果TimerTask拋出了未檢查異常則會導致Timer線程終止,同時Timer也不會重新恢復線程的執行,它會錯誤的為整個Timer線程都會取消。同時,已經被安排單尚未執行的TimerTask也不會再執行了,新的任務也不能被調度。故如果TimerTask拋出未檢查的異常,Timer將會產生無法預料的行為。
1、Timer管理時間延遲缺陷
Timer在執行定時定時任務時只會創建一個線程任務,如果存在多個線程,若其中某個線程因為某種原因而導致線程任務執行時間過長,超過了兩個任務的時間間隔,會發生一些缺陷:
----------------------------------------------------------------------------------
----------------------------------------------------------------------------------
----------------------------------------------------------------------------------
運行結果:
timerOne invoked ,the time:Thu Jul 07 13:18:05 CST 2016
timerTwo invoked ,the time:Thu Jul 07 13:18:10 CST 2016
按照我們正常思路,timerTwo應該是在3s后執行,其結果應該是:
?
timerOne invoked ,the time:Thu Jul 07 13:18:05 CST 2016
?
timerTwo invoked ,the time:Thu Jul 07 13:18:07 CST 2016
但是事與愿違,timerOne由于sleep(5000),休眠了4S,同時Timer內部是一個線程,導致timeOne所需的時間超過了間隔時間。
2、Timer拋出異常缺陷
如果TimerTask拋出RuntimeException,Timer會終止所有任務的運行。如下:
------------------------------------------------------------------------
------------------------------------------------------------------------
-------------------------------------------------------------------------
運行結果:timerOne拋出異常,導致timerTwo任務終止。
對于Timer的缺陷,我們可以考慮用ScheduledThreadPoolExecutor來替代。Timer是基于絕對時間的,對系統時間比較敏感,而ScheduledThreadPoolExecutor則是基于相對時間的;Timer是內部單一線程,而ScheduledThreadPoolExecutor內部是一個線程池,所以可以支持多個任務并發執行。
?
轉載于:https://www.cnblogs.com/vanl/p/5647050.html
總結
以上是生活随笔為你收集整理的Java之定时任务详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用tomcat自带的连接池,报错
- 下一篇: ***PHP中error_reporti