Seit Java 7 System.nanoTime()
ist die Sicherheit durch die JDK-Spezifikation garantiert. System.nanoTime()
Javadoc macht deutlich, dass alle beobachteten Aufrufe innerhalb einer JVM (dh über alle Threads hinweg) monoton sind:
Der zurückgegebene Wert repräsentiert Nanosekunden seit einer festen, aber willkürlichen Ursprungszeit (möglicherweise in der Zukunft, daher können die Werte negativ sein). Der gleiche Ursprung wird von allen Aufrufen dieser Methode in einer Instanz einer virtuellen Java-Maschine verwendet. Andere Instanzen virtueller Maschinen verwenden wahrscheinlich einen anderen Ursprung.
Die JVM / JDK-Implementierung ist dafür verantwortlich, die Inkonsistenzen auszubügeln, die beim Aufrufen der zugrunde liegenden Betriebssystem-Dienstprogramme auftreten können (z. B. die in der Antwort von Tom Anderson genannten ).
Die meisten anderen alten Antworten auf diese Frage (geschrieben 2009–2012) drücken FUD aus, das wahrscheinlich für Java 5 oder Java 6 relevant war, aber für moderne Versionen von Java nicht mehr relevant ist.
Es ist jedoch erwähnenswert, dass es trotz der nanoTime()
Sicherheit von JDK-Garantien mehrere Fehler in OpenJDK gab, die dazu führten, dass diese Garantie auf bestimmten Plattformen oder unter bestimmten Umständen nicht eingehalten wurde (z. B. JDK-8040140 , JDK-8184271 ). Derzeit gibt es keine offenen (bekannten) Fehler in OpenJDK nanoTime()
, aber die Entdeckung eines neuen solchen Fehlers oder eine Regression in einer neueren Version von OpenJDK sollte niemanden schockieren.
In diesem Sinne sollte Code, der nanoTime()
für zeitgesteuertes Blockieren, Warten auf Intervalle, Zeitüberschreitungen usw. verwendet wird, negative Zeitdifferenzen (Zeitüberschreitungen) vorzugsweise als Nullen behandeln, anstatt Ausnahmen auszulösen. Diese Praxis ist auch bevorzugt , weil es mit dem Verhalten aller zeitlichen Warten Methoden in allen Klassen in Einklang steht java.util.concurrent.*
, zum Beispiel Semaphore.tryAcquire()
, Lock.tryLock()
, BlockingQueue.poll()
etc.
Dennoch nanoTime()
sollte für die Implementierung von zeitgesteuertem Blockieren, Warten auf Intervalle, Zeitüberschreitungen usw. immer noch bevorzugt werden, currentTimeMillis()
da letzteres dem Phänomen "Rücklaufzeit" unterliegt (z. B. aufgrund der Serverzeitkorrektur), dh currentTimeMillis()
nicht zum Messen von Zeitintervallen geeignet ist überhaupt. Weitere Informationen finden Sie in dieser Antwort .
Anstatt die nanoTime()
Messungen der Codeausführungszeit direkt zu verwenden, sollten vorzugsweise spezielle Benchmarking-Frameworks und -Profiler verwendet werden, z. B. JMH und Async-Profiler im Wall-Clock-Profiling-Modus .