2010-04-30 64 views
5

我正在使用ScheduledThreadPoolExecutor對象調度任務。我使用下面的方法:ScheduledThreadPoolExecutor由於CPU時間差異而執行錯誤的時間

public ScheduledFuture<?> schedule(Runnable command, long delay,TimeUnit unit) 

和設置延遲爲30秒(延遲= 30,000和單元= TimeUnit.MILLISECONDS)。有時我的任務會立即發生,其他時間需要70秒。

我相信ScheduledThreadPoolExecutor使用CPU特定的時鐘。當我運行比較System.currentTimeMillis的(),System.nanoTime()[其爲CPU具體]試驗我看到以下

時間表:1272637682651ms,7858346157228410ns

執行:1272637682667ms,7858386270968425ns

差16毫秒但4011374001ns(或40,113ms)

,所以它看起來像有40秒

兩款CPU時鐘之間的矛盾如何解決這個問題,我n java代碼?不幸的是,這是一臺客戶機,我無法修改他們的系統。

+0

棘手的一個。也許'java.util.Calendar'會有幫助嗎? Calendar.getInstance()等等。 – 2010-04-30 16:00:37

+1

你是否在虛擬機(VMWare,KVM,Virtual PC)上運行此代碼?即使在毫秒級別,虛擬化也會對CPU時鐘造成嚴重破壞。 – 2010-05-01 07:17:17

+0

它直接在Windows XP Profession機器上運行。沒有虛擬化。 – richs 2010-05-03 13:13:51

回答

2

是的,你說的是ScheduledThreadPoolExecutor使用System.nanoTime()。你也是對的,System.nanoTime()依賴於特定的系統實例。如果您的流程恰好在計劃和執行之間遷移,那麼您運氣不佳。 (我不認爲在多CPU系統上的CPU之間遷移會很重要,但也許它確實有影響嗎?當然,如果您在虛擬機中運行並且虛擬機在主機之間遷移,那麼這一點很重要)。

我認爲在這種情況下唯一真正的解決方案是使用ScheduledThreadPoolExecutor以外的東西......這不是一個簡單的方法,只是改變ScheduledThreadPoolExecutor.now()。 AbstractQueuedSynchronizer $ ConditionObject.awaitNanos()也使用System.nanoTime()。

我的其中一個項目使用Quartz進行作業調度,我從來沒有見過您用該庫描述的問題。我不知道實現細節(也許它只是使用System.nanoTime(),但也許不是?)。