jdk定時器Timer在實際應用中異常中止的問題排查及解決方法

小編為程序員一枚,在一次項目過程中,客戶反映系統某個定時任務的功能不能正常運行了,每當這個時候小編都會眉頭一緊,怎麼會?同行們是不是有同樣的感覺?心裡想,我整的東西,怎麼能不行了呢?肯定是客戶整錯了。。。。。。。。。。。。哎?不對。難道真的不行了?還是去查一下吧。經過看後台日誌,反覆琢磨,也沒能找出原因所在。沒辦法,拿了日誌自己回去再研究吧。

藉助度娘的幫助,加上日誌中的反饋,最終確定Timer定時器停止了。原來,timer定時器是jdk自帶的一個定時器工具類,如果在TimerTask里拋出了異常,那麼Timer認為定時任務被取消並終止執行線程,不再執行,直到被再次手動調起或者重啟項目服務。TimerTask定時器任務中有一段邏輯處理,在處理數據的時候,由於某些數據不合法,導致業務邏輯拋出了項目 中的自定義異常,而程序又未捕獲該異常,最終定時器掛了,客戶找來了。

Advertisements

小編用的是下面的方法,

scheduleAtFixedRate

public void scheduleAtFixedRate(TimerTask task, Date firstTime,long period)
  • 安排指定的任務在指定的時間開始進行重複的固定速率執行。以近似固定的時間間隔(由指定的周期分隔)進行後續執行。

    在固定速率執行中,相對於已安排的初始執行時間來安排每次執行。如果由於任何原因(如垃圾回收或其他後台活動)而延遲了某次執行,則將快速連續地出現兩次或更多次執行,從而使後續執行能夠趕上來。從長遠來看,執行的頻率將正好是指定周期的倒數(假定 Object.wait(long) 所依靠的系統時鐘是準確的)。

    Advertisements

    固定速率執行適用於那些對絕對 時間敏感的重複執行活動,如每小時準點打鐘報時,或者在每天的特定時間運行已安排的維護活動。它還適用於那些完成固定次數執行的總計時間很重要的重複活動,如倒計時的計時器,每秒鐘滴答一次,共 10 秒鐘。最後,固定速率執行適用於安排多次重複執行的計時器任務,這些任務相互之間必須保持同步。

    • 參數:

    • task - 所要安排的任務。

    • firstTime - 首次執行任務的時間。

    • period - 執行各後續任務之間的時間間隔,單位是毫秒。

    • 拋出:

    • IllegalArgumentException - 如果 time.getTime() 是負數。

    • IllegalStateException - 如果已經安排或取消了任務,已經取消了計時器,或者計時器線程已終止。

下面就是來解決問題了。

首先要捕獲業務邏輯裡面可能拋出的任何異常,注意,是任何,也就是所有的異常。

try {

run();

} catch (Exception e) {

// TODO Auto-generated catch block

}

經查閱資料加上網友們的反饋,大家覺得Timer定時器不可靠,同時Timer執行周期任務時依賴系統時間,如果當前系統時間發生變化會出現一些執行上的變化,所以最終採用了第二種方法:用線種池ScheduledThreadPoolExecutor的實現類ScheduledExecutorService去做。

scheduleAtFixedRate

public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,long initialDelay,long period, TimeUnit unit)
  • 從介面 ScheduledExecutorService 複製的描述

  • 指定者:

  • 介面 ScheduledExecutorService 中的 scheduleAtFixedRate

  • 創建並執行一個在給定初始延遲后首次啟用的定期操作,後續操作具有給定的周期;也就是將在 initialDelay 后開始執行,然後在 initialDelay+period 后執行,接著在 initialDelay + 2 * period 后執行,依此類推。如果任務的任何一個執行遇到異常,則後續執行都會被取消。否則,只能通過執行程序的取消或終止方法來終止該任務。如果此任務的任何一個執行要花費比其周期更長的時間,則將推遲後續執行,但不會同時執行。

  • 參數:

  • command - 要執行的任務

  • initialDelay - 首次執行的延遲時間

  • period - 連續執行之間的周期

  • unit - initialDelay 和 period 參數的時間單位

  • 返回:

  • 表示掛起任務完成的 ScheduledFuture,並且其 get() 方法在取消后將拋出異常

希望這樣處理之後不會再有問題。小編拙見,如有問題,請指正。謝謝。

Advertisements

你可能會喜歡