2010-04-30 4 views
5

Sto pianificando un'operazione utilizzando un oggetto ScheduledThreadPoolExecutor. Uso il seguente metodo:ScheduledThreadPoolExecutor che esegue un orario errato a causa della discrepanza temporale della CPU

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

e impostare il ritardo di 30 secondi (delay = 30.000 e unità = TimeUnit.MILLISECONDS). A volte il mio compito si verifica immediatamente e altre volte ci vogliono 70 secondi.

Credo che ScheduledThreadPoolExecutor utilizzi orologi specifici della CPU. Quando ho eseguito prove di confronto System.currentTimeMillis(), System.nanoTime() [che è CPU specifico] compaiono i seguenti

pianificazione: 1272637682651ms, 7858346157228410ns

eseguire: 1272637682667ms, 7858386270968425ns

differenza 16ms ma 4011374001ns (o 40,113ms)

così sembra ci sia discrepanza tra due orologi CPU di 40 secondi

Come risolvo questo problema i n codice java? Sfortunatamente questa è una macchina client e non posso modificare il loro sistema.

+0

Ingannevole. Potrebbe essere utile 'java.util.Calendar'? Calendar.getInstance() e così via. –

+1

Stai eseguendo questo codice su una macchina virtuale (VMWare, KVM, Virtual PC)? La virtualizzazione può causare il caos con l'orologio della CPU, anche a un millisecondo. –

+0

È in esecuzione direttamente su un computer Windows XP. Nessuna virtualizzazione. – richs

risposta

2

Sì, hai ragione che ScheduledThreadPoolExecutor utilizza System.nanoTime(). E hai anche ragione che System.nanoTime() dipende dalla particolare istanza di sistema. Se il tuo processo dovesse migrare tra la pianificazione e l'esecuzione, allora sei sfortunato. (Non penserei che la migrazione tra le CPU su un sistema multi-CPU sarebbe importante, ma forse è così? Certo che sarebbe importante se si sta eseguendo in una VM e la VM migrata tra gli host).

Penso che l'unica soluzione reale in questo caso sia l'utilizzo di qualcosa di diverso da ScheduledThreadPoolExecutor ... Non è un semplice cambio di ScheduledThreadPoolExecutor.now(). AbstractQueuedSynchronizer $ ConditionObject.awaitNanos() utilizza anche System.nanoTime().

Uno dei miei progetti utilizza Quartz per la pianificazione del lavoro e non ho mai visto il problema che descrivi con quella libreria. Non conosco i dettagli di implementazione (forse usa solo System.nanoTime(), ma forse no?).