Esiste una particolarità che ho riscontrato durante l'utilizzo di esecutori pianificati Java e mi chiedevo se ciò che provavo fosse normale.Precisione esecutore pianificato Java
Devo pianificare le attività che vengono eseguite a una velocità predefinita di 5 secondi. Si prevede che queste attività richiederanno di volta in volta più di 5 secondi, ma quando il tempo necessario per eseguirle scende sotto i 5 secondi, l'elenco di backup delle attività dovrebbe essere eseguito in rapida successione per recuperare il ritardo. Quando si eseguono le attività, è importante sapere qual è il tempo di esecuzione pianificato originale (si pensi a scheduledExecutionTime()
in java.util.TimerTask
). Infine, ho bisogno di tracciare la differenza tra il tempo programmato e il tempo reale per identificare quando il programma è "alla deriva" e di quanto.
Finora ho realizzato tutto questo utilizzando esecutori Java, e la seguente classe illustra l'idea generale:
public class ExecutorTest {
public static final long PERIOD = 5000;
public static void main(String[] args) {
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(
new Command(), 0, PERIOD, TimeUnit.MILLISECONDS);
}
private static final class Command implements Runnable {
long timestamp = 0;
public void run() {
long now = System.currentTimeMillis();
if (timestamp == 0) {
timestamp = now;
}
// Drift is the difference between scheduled time and execution time
long drift = now - timestamp;
String format = "Ran at %1$tF %<tT,%<tL; drift: %2$dms";
System.out.println(String.format(format, now, drift));
timestamp += PERIOD;
}
}
}
L'esecuzione del codice di cui sopra dimostra che la deriva (che idealmente dovrebbe essere il più vicino a 0 possibile) fluttua di pochi secondi, il cui risultato è che i compiti vengono eseguiti prematuramente o in ritardo. Ho creato un grafico dai risultati di funzionamento di questo per circa 150 minuti:
Quindi la mia prima domanda è se questo è normale. Il mio ambiente è costituito da Windows XP a 32 bit e aggiornamento 21 di Java 1.5 (sebbene l'aggiornamento 22 di Java 6 produca risultati simili).
La seconda domanda è se esiste un modo semplice per ridurre la quantità di deriva. Se utilizzo un semplice java.util.Timer
o anche solo Thread.sleep()
, la deriva è inesistente.
Infine, c'è un modo migliore per tenere traccia del tempo di esecuzione pianificato quando si usano gli esecutori programmati?