2013-01-10 39 views
5

我用ScheduledExecutorService.scheduleAtFixedRate運行每日任務,像這樣:精度ScheduledExecutorService的中/ JVM

executor.scheduleAtFixedRate(task, d, 24L * 3600 * 1000, TimeUnit.MILLISECONDS); 

d是以毫秒爲單位的初始延遲)。

執行者由Executors.newSingleThreadScheduledExecutor()創建並運行多個任務,但它們都安排在相隔幾小時,最多花費幾分鐘時間。

我知道ScheduledExecutorService不能保證準確性,我需要一個實時操作系統和JVM來獲取它。雖然這不是我的任務的要求。

我注意到,在Windows 2003 Server上,使用JDK 1.7.0_03,任務每天滑動將近10秒。這大約每月5分鐘,這是我的應用程序可以接受的。無論如何,我可能必須實施重新計劃,因爲我希望任務能夠在特定的當地時間運行,所以我必須自己照顧DST。該服務運行很長一段時間 - 半年不重啓並不是那麼不尋常。

儘管如此,我認爲對於大多數閒置系統來說,10秒/天的不準確度相當高,我不知道是否應該爲更糟糕的行爲做好準備。

所以我的問題是關於你的經驗scheduleAtFixedRate。 10秒/天是正常的嗎?在其他環境(我們的客戶還使用Linux和Solaris服務器)中,我會得到更好還是更差的準確性?或者10秒錶明我們的環境中有什麼不對勁?

+1

注意:'24L * 3600 * 1000,TimeUnit.MILLISECONDS'相當於'1,TimeUnit.DAYS' ...這就是整個時間點單元:避免時間單位轉換! – assylias

+1

@assylias yes,但initialDelay d以毫秒爲單位,並且只有一個TimeUnit參數。 – Chris

+1

我會在特定的本地時間使用Quartz或Spring'task:scheduled-tasks'來觸發,那麼你就沒有這個問題。 – luukes

回答

2

對於長時間運行的任務來說,這並不令人感到意外。另一個問題是它使用nanoTime(),它不與NTP等同步。這可能會導致與掛鐘漂移。

避免這種情況的一種方法是按照您的建議重複計劃。重複任務實際上會重新安排自己(這就是爲什麼他們不會拋出異常,請參閱下文)。您可以執行一次性任務,最後重新安排自己,使用掛鐘時間並考慮節約日期列表。

順便說一句:我會確保你捕獲一個異常甚至Throwable拋出。如果你的任務不會停止,可能會默默地(除非你正在看Future對象返回)

我所做的就是欺騙一點。我有一項任務每10秒鐘醒來一次,並檢查是否需要運行,如果不運行。如果你沒有數以千計的任務並且實現起來更簡單,那麼開銷通常是微不足道的。