2010-04-30 11 views
5

Planuję zadanie za pomocą obiektu ScheduledThreadPoolExecutor. Używać w następujący sposób:ScheduledThreadPoolExecutor wykonanie niewłaściwego czasu z powodu niezgodności czasu procesora

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

i ustawienie opóźnienia do 30 sekund (opóźnienie = 30000 jednostka = TimeUnit.MILLISECONDS). Czasami moje zadanie pojawia się natychmiast, a czasami zajmuje to 70 sekund.

Wierzę, że ScheduledThreadPoolExecutor wykorzystuje zegary specyficzne dla procesora. Kiedy wykonywanie testów porównujące System.currentTimeMillis, System.nanoTime()() [który procesor specyficzne] i są opisane w następujących

planu: 1272637682651ms, 7858346157228410ns

wykonania: 1272637682667ms, 7858386270968425ns

Różnica polega 16ms ale 4011374001ns (lub 40,113ms)

tak wygląda istnieje rozbieżność pomiędzy dwoma zegarami procesora 40 sekund

Jak rozwiązać ten problem i n kodu java? Niestety jest to maszyna klienta i nie mogę zmodyfikować ich systemu.

+0

Tricky one. Może "java.util.Calendar" będzie pomocny? Calendar.getInstance() i tak dalej .. –

+1

Czy ten kod jest uruchamiany na maszynie wirtualnej (VMWare, KVM, Virtual PC)? Wirtualizacja może spowodować spustoszenie w zegarze procesora, nawet na poziomie milisekund. –

+0

Działa bezpośrednio na komputerze z Windows XP Profession. Brak wirtualizacji. – richs

Odpowiedz

2

Tak, masz rację, że ScheduledThreadPoolExecutor używa System.nanoTime(). I masz rację, że System.nanoTime() zależy od konkretnej instancji systemu. Jeśli twój proces przechodzi migrację między harmonogramem a wykonaniem, nie masz szczęścia. (Nie sądzę, że migracja pomiędzy procesorami w systemie wieloprocesorowym ma znaczenie, ale może tak jest? Z pewnością ma to znaczenie, jeśli używasz maszyny wirtualnej, a maszyna wirtualna migruje między hostami).

Myślę, że jedynym prawdziwym rozwiązaniem w tym przypadku jest użycie czegoś innego niż ScheduledThreadPoolExecutor ... To nie jest proste, jak tylko zmiana ScheduledThreadPoolExecutor.now() albo. AbstractQueuedSynchronizer $ ConditionObject.awaitNanos() również używa System.nanoTime().

Jeden z moich projektów wykorzystuje Quartz do planowania zadań i nigdy nie widziałem problemu, który opisujesz w tej bibliotece. Nie znam szczegółów implementacji (może po prostu używa System.nanoTime(), ale może nie?).

Powiązane problemy