2012-02-08 16 views
10

Necesito crear una marca de tiempo (en milisegundos) en Java que garantice ser única en esa instancia de VM en particular. Es decir. necesita alguna forma de acelerar el rendimiento de System.currentTimeMillis() para que devuelva como máximo un resultado cada ms. ¿Alguna idea sobre cómo implementar eso?Creación de una marca de tiempo única en Java

+2

no estoy seguro de qué quiere decir * * estrangulación currentTimeMillis() para que devuelva * * como máximo un resultado ev ery ms? Si desea marcas de tiempo únicas, prefiere garantizar que devuelve un valor diferente en cada llamada, ¿verdad? –

+0

¿Tienen que aumentar monótonamente? ¿Tienen que tener alguna relación con * time * real? ¿Tienen que ser únicos en múltiples ejecuciones? –

Respuesta

30

Esto dará un tiempo tan cerca de la hora actual como sea posible sin duplicados.

private static final AtomicLong LAST_TIME_MS = new AtomicLong(); 
public static long uniqueCurrentTimeMS() { 
    long now = System.currentTimeMillis(); 
    while(true) { 
     long lastTime = LAST_TIME_MS.get(); 
     if (lastTime >= now) 
      now = lastTime+1; 
     if (LAST_TIME_MS.compareAndSet(lastTime, now)) 
      return now; 
    } 
} 

Una forma de evitar la limitación de una identificación por mili-segundo es utilizar una marca de tiempo micro-segunda. es decir, multiplicar CurrentTimeMS por 1000. Esto permitirá 1000 ids por mili-segundo.

Nota: si el tiempo va hacia atrás, por ejemplo, debido a una corrección NTP, el tiempo simplemente progresará a 1 milisegundo por invocación hasta que el tiempo llegue. ;)

+0

Gracias! ¡Exactamente lo que necesitaba! – Yrlec

+0

Utilizado correctamente, esto significa que tendrá identificadores únicos incluso después de reiniciar su aplicación. –

+1

¡Suena bien! ¿Qué significa "usado correctamente" con mayor precisión? – Yrlec

1

Puede usar System.nanoTime(), que es el temporizador de sistema más preciso disponible, y dividirlo por millones para obtener milisegundos. Si bien no hay garantías formales sobre la frecuencia con que se actualiza, creo que es razonable suponer que se actualiza mucho más (orden (es) de magnitud) con frecuencia que una vez por milisegundo. Por supuesto, si crea marcas de tiempo enteras en menos de un intervalo de milisegundos, entonces no todas pueden ser únicas.

Tenga en cuenta que el valor absoluto nanoTime() es arbitrario. Si desea tiempo absoluto, calibre de alguna manera, es decir, compárelo con currentTimeMillis() al comenzar.

4

Puede utilizar System.nanoTime() para una mayor precisión

Aunque traté de abajo y cada vez que se da valores diferentes, es probable que no se garantiza que sea único en todo momento.

public static void main(String[] args) { 
     long time1 = System.nanoTime(); 
     long time2 = System.nanoTime(); 
     long time3 = System.nanoTime(); 
     System.out.println(time1); 
     System.out.println(time2); 
     System.out.println(time3); 
    } 

Otra forma es utilizar AtomicInteger/AtomicLong clases de números únicos si el tiempo no es importante para usted y sólo tiene número único, esto probablemente es una opción btter.

+2

nanoTime es monótono, pero no siempre único. Puedes obtener muchos duplicados. p.ej. en Red Hat y Centos 5.x la resolución es de micro segundos, por lo que obtienes muchos valores repetidos. –

+0

Gracias por la información. Supuse que depende del sistema operativo y la máquina. – fmucar

+1

Puede usar nanoTime con un control que sea diferente. (Similar a mi solución) El nanoTime es el tiempo de actividad en segundos en muchos sistemas. –

1

bien la búsqueda de una solución me encontré con ULIB (único universal lexicográfico Sortable Identificador) https://github.com/huxi/sulky/tree/master/sulky-ulid/

No es mucho, pero más corto entonces UUID.

Un Ulid:

  • es compatible con UUID/GUID de 1.21e + 24 ULIDs únicas por milisegundo (1,208,925,819,614,629,174,706,176 para ser exactos)
  • lexicográfico que se pueden ordenar
  • canónicamente codificados como una cadena de 26 caracteres, en comparación con el UUID de 36 caracteres
  • Usos base32 Crockford para una mayor eficacia y facilidad de lectura (5 bits por carácter)
  • Caso insensible
  • no hay caracteres especiales (URL segura)
Cuestiones relacionadas