¿System.currentTimeMillis siempre devolverá un valor> = llamadas anteriores?

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html#currentTimeMillis () dice:

Devuelve la hora actual en milisegundos. Tenga en cuenta que si bien la unidad de tiempo del valor de retorno es un milisegundo, la granularidad del valor depende del sistema operativo subyacente y puede ser mayor. Por ejemplo, muchos sistemas operativos miden el tiempo en unidades de decenas de milisegundos.

No tengo claro si tengo la garantía de que este código siempre imprimirá números cada vez mayores (o los mismos).

while (1) { System.out.println(System.currentTimeMillis() ); } 

La respuesta corta es no, System.currentTimeMillis() no es monotónico. Se basa en el tiempo del sistema y, por lo tanto, puede estar sujeto a variaciones en ambos sentidos (hacia delante o hacia atrás) en el caso de ajustes de reloj (por ejemplo, a través de NTP ).

System.nanoTime() es monotónico, si y solo si la plataforma subyacente es compatible con CLOCK_MONOTONIC ; consulte los comentarios sobre el informe de errores de Java 6458294 para obtener una buena descripción en algunas circunstancias donde esto es / no es cierto.

(Y, como anécdota adicional, personalmente he observado (varias veces) System.currentTimeMillis() ejecutar ‘hacia atrás’, en ausencia de ajustes de reloj, a través de hilos, es decir, una llamada a ese método en un hilo devolvió una valor más bajo que una llamada en otro hilo, a pesar de que ocurrió cronológicamente después en “tiempo real”)

Si necesita una fuente monotónica, System.nanoTime() en una plataforma compatible con la monotonía es su mejor opción.

No, no siempre será> = todas las llamadas anteriores.

  • Puede que no aumente cada vez si lo llamas varias veces en rápida sucesión del mismo hilo (sé que esta es la = parte de> =, pero el comportamiento a menudo sorprende a las personas).

  • Si lo llama varias veces en sucesión rápida desde varios subprocesos, podría hacer cualquier cantidad de cosas: podría ir un poco atrás en el tiempo entre subprocesos por una cantidad muy pequeña, dependiendo de la implementación y la posibilidad aleatoria.

  • Lo que es más grave, el valor podría retroceder en el tiempo en una gran cantidad si el usuario (raro) o una sincronización NTP (potencialmente común) ajusta el reloj del sistema.

No se puede garantizar que aumente, ya que el usuario podría cambiar el tiempo del sistema entre llamadas.

Además de eso, debería seguir aumentando ya que representa milisegundos desde la época. Si fuera un “tiempo de pared” normal, tendría que preocuparse por los cambios de hora en el día bisiesto o en el cambio de horario de verano.

Si desea un valor que aumente de manera monótona, puede hacer algo como.

 public enum Time { ; private static long lastTime; public synchronized static long increasingTimeMillis() { long now = System.currentTimeMillis(); if (now > lastTime) return lastTime = now; return ++lastTime; } } 

Mientras llame a esto menos de mil veces por segundo, su tiempo creciente no se alejará demasiado del tiempo real, pero será único. (Esto puede funcionar, incluso si reinicia su aplicación)

@Mark Rushakoff tiene razón; nanoTime() puede ser un poco más confiable.

Adición: tenga en cuenta estas advertencias , citadas por @Steven Schlansker.