416 Stimmen

System.currentTimeMillis vs. System.nanoTime

Genauigkeit vs. Präzision

Was ich gerne wissen möchte, ist, ob ich Folgendes verwenden sollte System.currentTimeMillis() o System.nanoTime() wenn ich die Positionen meiner Objekte in meinem Spiel aktualisiere? Ihre Bewegungsänderung ist direkt proportional zu der seit dem letzten Aufruf verstrichenen Zeit, und ich möchte so präzise wie möglich sein.

Ich habe gelesen, dass es einige ernsthafte Probleme mit der Zeitauflösung zwischen verschiedenen Betriebssystemen gibt (nämlich dass Mac/Linux eine Auflösung von fast 1 ms hat, während Windows eine Auflösung von 50 ms hat). Ich bin in erster Linie läuft meine Anwendungen auf Windows und 50ms Auflösung scheint ziemlich ungenau.

Gibt es bessere Möglichkeiten als die beiden von mir genannten?

Irgendwelche Vorschläge/Kommentare?

346voto

dancavallaro Punkte 12769

Wenn Sie nur extrem präzise Messungen von verstrichene Zeit verwenden System.nanoTime() . System.currentTimeMillis() gibt Ihnen die genauest mögliche verstrichene Zeit in Millisekunden seit der Epoche, aber System.nanoTime() gibt Ihnen eine nanosekundengenaue Zeit, bezogen auf einen beliebigen Punkt.

Aus der Java-Dokumentation:

public static long nanoTime()

Gibt den aktuellen Wert des genauesten verfügbaren Systemtimers in Nanosekunden zurück.

Diese Methode kann nur verwendet werden, um verstrichene Zeit zu messen und hat keinen mit einem anderen Begriff von System- oder oder Wanduhr-Zeit. Der zurückgegebene Wert repräsentiert Nanosekunden seit einem festen, aber willkürlichen Herkunft Zeit (vielleicht in der Zukunft, daher können die Werte negativ sein). Diese Methode liefert Nanosekundengenauigkeit, aber nicht nicht unbedingt Nanosekundengenauigkeit. Keine Garantien darüber gegeben, wie häufig häufig sich die Werte ändern. Unterschiede in aufeinanderfolgenden Aufrufen, die sich über mehr als als etwa 292 Jahre (2 63 Nanosekunden) wird nicht genau die verstrichene Zeit aufgrund eines numerischen Überlauf.

Zum Beispiel, um zu messen, wie lange ein Code zur Ausführung braucht:

long startTime = System.nanoTime();    
// ... the code being measured ...    
long estimatedTime = System.nanoTime() - startTime;

Siehe auch: JavaDoc System.nanoTime() y JavaDoc System.currentTimeMillis() für weitere Informationen.

123voto

gub Punkte 4859

Da dies noch niemand erwähnt hat

Es ist nicht sicher, die Ergebnisse von System.nanoTime() Aufrufen zwischen verschiedenen JVMs, kann jede JVM eine unabhängige "Ursprungszeit" haben.

System.currentTimeMillis() gibt in allen JVMs den (ungefähren) gleichen Wert zurück, da er an die Systemuhrzeit gebunden ist.

Wenn Sie die Zeit berechnen wollen, die zwischen zwei Ereignissen verstrichen ist, wie bei einer Stoppuhr, verwenden Sie nanoTime() Änderungen in der Systemwanduhr machen currentTimeMillis() für diesen Anwendungsfall falsch.

60voto

Michael Burr Punkte 320591

Aktualisierung durch Arkadij : Ich habe ein korrekteres Verhalten von System.currentTimeMillis() unter Windows 7 in Oracle Java 8. Die Zeit wurde mit einer Genauigkeit von 1 Millisekunde zurückgegeben. Der Quellcode in OpenJDK hat sich nicht geändert, daher weiß ich nicht, was das bessere Verhalten verursacht.


David Holmes von Sun hat vor ein paar Jahren einen Blog-Artikel veröffentlicht, der einen sehr detaillierten Blick auf die Java Timing APIs wirft (insbesondere auf System.currentTimeMillis() y System.nanoTime() ), wann Sie welche verwenden sollten und wie sie intern funktionieren.

Innerhalb der Hotspot-VM: Uhren, Timer und Zeitplanungsereignisse - Teil I - Windows

Ein sehr interessanter Aspekt des Timers, der von Java unter Windows für APIs verwendet wird, die einen zeitlich begrenzten Warteparameter haben, ist, dass die Auflösung des Timers sich ändern kann, je nachdem, welche anderen API-Aufrufe gemacht wurden - systemweit (nicht nur in dem jeweiligen Prozess). Er zeigt ein Beispiel, bei dem die Verwendung von Thread.sleep() wird diese Auflösungsänderung bewirken.

12voto

KarlU Punkte 447

Wie bereits erwähnt, ist currentTimeMillis die Uhrzeit, die sich aufgrund der Sommerzeit ändert ( nicht: Sommerzeit und Zeitzone haben nichts mit currentTimeMillis zu tun, der Rest ist wahr ), Benutzer, die die Zeiteinstellungen ändern, Schaltsekunden und Internet-Zeitsynchronisierung. Wenn Ihre Anwendung von monoton ansteigenden Zeitwerten abhängt, sollten Sie stattdessen nanoTime bevorzugen.

Man könnte meinen, dass die Spielerinnen und Spieler während des Spiels nicht an den Zeiteinstellungen herumfummeln werden, und damit hätte man vielleicht recht. Aber unterschätzen Sie nicht die Unterbrechung durch die Zeitsynchronisation im Internet oder vielleicht durch Remote-Desktop-Benutzer. Die nanoTime-API ist gegen diese Art von Störungen immun.

Wenn Sie die Uhrzeit verwenden, aber Unregelmäßigkeiten aufgrund der Internet-Zeitsynchronisation vermeiden wollen, sollten Sie einen NTP-Client wie Meinberg in Betracht ziehen, der die Uhrzeit "abstimmt", um sie auf Null zu setzen, anstatt die Uhr nur regelmäßig neu einzustellen.

Ich spreche aus persönlicher Erfahrung. In einer Wetteranwendung, die ich entwickelt habe, bekam ich zufällig auftretende Spitzen der Windgeschwindigkeit. Es dauerte eine Weile, bis ich erkannte, dass meine Zeitbasis durch das Verhalten der Uhrzeit auf einem typischen PC gestört wurde. Alle meine Probleme verschwanden, als ich begann, nanoTime zu verwenden. Konsistenz (Monotonie) war für meine Anwendung wichtiger als rohe Präzision oder absolute Genauigkeit.

11voto

Paul Morel Punkte 551

System.nanoTime() wird in älteren JVMs nicht unterstützt. Wenn das ein Problem ist, bleiben Sie bei currentTimeMillis

Was die Genauigkeit betrifft, haben Sie fast recht. Auf EINIGEN Windows-Rechnern, currentTimeMillis() hat eine Auflösung von etwa 10ms (nicht 50ms). Ich bin mir nicht sicher, warum, aber einige Windows-Rechner sind genauso genau wie Linux-Rechner.

Ich habe verwendet GAGETimer in der Vergangenheit mit mäßigem Erfolg angewandt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X