Desde Java 7, System.nanoTime()
se garantiza la seguridad de la especificación JDK. System.nanoTime()
'Javadoc deja en claro que todas las invocaciones observadas dentro de una JVM (es decir, en todos los hilos) son monótonas:
El valor devuelto representa nanosegundos desde un tiempo de origen fijo pero arbitrario (quizás en el futuro, por lo que los valores pueden ser negativos). Todas las invocaciones de este método utilizan el mismo origen en una instancia de una máquina virtual Java; Es probable que otras instancias de máquinas virtuales utilicen un origen diferente.
La implementación de JVM / JDK es responsable de resolver las inconsistencias que podrían observarse cuando se llaman las utilidades subyacentes del sistema operativo (por ejemplo, las mencionadas en la respuesta de Tom Anderson ).
La mayoría de las otras respuestas antiguas a esta pregunta (escritas en 2009-2012) expresan FUD que probablemente fue relevante para Java 5 o Java 6, pero ya no es relevante para las versiones modernas de Java.
Sin embargo, vale la pena mencionar que, a pesar de nanoTime()
la seguridad de las garantías de JDK , ha habido varios errores en OpenJDK que hacen que no se mantenga esta garantía en ciertas plataformas o bajo ciertas circunstancias (por ejemplo, JDK-8040140 , JDK-8184271 ). No hay errores abiertos (conocidos) en OpenJDK wrtnanoTime()
en este momento, pero el descubrimiento de un nuevo error o una regresión en una versión más reciente de OpenJDK no debería sorprender a nadie.
Con eso en mente, el código que se usa nanoTime()
para el bloqueo temporizado, la espera de intervalos, los tiempos de espera, etc., debe tratar preferiblemente las diferencias de tiempo negativas (tiempos de espera) como ceros en lugar de arrojar excepciones. Esta práctica también es preferible porque es coherente con el comportamiento de todos los métodos de espera cronometrados en todas las clases en java.util.concurrent.*
, por ejemplo Semaphore.tryAcquire()
, Lock.tryLock()
,BlockingQueue.poll()
, etc.
No obstante, nanoTime()
aún se debe preferir para implementar el bloqueo temporizado, el intervalo de espera, los tiempos de espera, etc., currentTimeMillis()
ya que este último está sujeto al fenómeno del "tiempo que retrocede" (por ejemplo, debido a la corrección de la hora del servidor), currentTimeMillis()
es decir, no es adecuado para medir intervalos de tiempo en absoluto. Ver esta respuesta para más información.
En lugar de utilizar nanoTime()
directamente para mediciones de tiempo de ejecución de código, se deben utilizar preferiblemente marcos de referencia y perfiladores especializados, por ejemplo JMH y async-profiler en modo de perfil de reloj de pared .