Ho bisogno di creare un timestamp (in millisecondi) in Java che è garantito essere univoco in quella particolare istanza VM. Cioè è necessario un modo per limitare il throughput di System.currentTimeMillis() in modo che restituisca al massimo un risultato ogni ms. Qualche idea su come implementarlo?Creazione di un timestamp univoco in Java
risposta
Questo darà un tempo il più vicino possibile al tempo corrente senza duplicati.
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;
}
}
Un modo per evitare la limitazione di un id al milli-secondo è quello di utilizzare un micro-secondo timestamp. cioè moltiplicare currentTimeMS per 1000. Ciò consentirà 1000 id per millisecondo.
Nota: se il tempo scorre indietro, ad es. A causa di una correzione NTP, il tempo progredisce a 1 milli-secondo per invocazione fino a quando il tempo non si avvicina. ;)
È possibile utilizzare System.nanoTime()
, che è il timer di sistema disponibile più preciso e dividerlo per milione per ottenere i millisecondi. Anche se non ci sono garanzie formali sulla frequenza con cui viene aggiornato, credo sia ragionevole presumere che aggiorni molto più (ordine/i di grandezza) frequentemente di una volta al millisecondo. Naturalmente, se crei timestamp interi di un intervallo inferiore a millisecondi, non possono essere tutti univoci.
Si noti che il valore assoluto nanoTime()
è arbitrario. Se si desidera il tempo assoluto, calibrarlo in qualche modo, cioè confrontarlo con currentTimeMillis()
all'avvio.
È possibile utilizzare System.nanoTime()
per una migliore precisione
Anche se ho provato qui sotto e ogni volta che si dà valori diversi, probabilmente non è garantito per essere unico per tutto il tempo.
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);
}
Un altro modo è quello di utilizzare AtomicInteger
/AtomicLong
classi per numeri unici, se il tempo non è importante per voi e basta numero unico, questo probabilmente è una scelta btter.
nanoTime è monotono, ma non sempre unico. Puoi ottenere molti duplicati. per esempio. su Red Hat & Centos 5.x la risoluzione è micro-secondi, quindi ottieni molti valori ripetuti. –
Grazie per le informazioni. Ho indovinato che dipende dal sistema operativo e dalla macchina. – fmucar
Puoi usare nanoTime con un controllo diverso. (Simile alla mia soluzione) Il nanoTime è il tempo di attività in meno di secondi su molti sistemi. –
Potrebbe forse fare uso di java.util.UUID
ed è timestamp()
e clockSequence()
?
Method Summary
int clockSequence()
The clock sequence value associated with this UUID.
long timestamp()
The timestamp value associated with this UUID.
Maggiori dettagli qui: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/UUID.html
Durante la ricerca di una soluzione mi sono imbattuto ULIB (Universally Unique lexicographically ordinabili Identifier) https://github.com/huxi/sulky/tree/master/sulky-ulid/
Non è una lunga, ma più corto quindi UUID.
A ULID:
- è compatibile con UUID/GUID di 1.21e + 24 ULIDs unici al millisecondo (1,208,925,819,614,629,174,706,176 per l'esattezza)
- lexicographically ordinabili
- Canonicamente codificate come una stringa di 26 caratteri, in contrapposizione all'UUID 36 carattere
- Utilizza base32 di Crockford per una migliore efficienza e leggibilità (5 bit per carattere)
- caso insensitive
- nessun carattere speciale (sicuro URL)
non sono sicuro di quello che vuoi dire * * limitazione currentTimeMillis() in modo che restituisca al massimo * * un risultato ev ery ms? Se desideri timestamp univoci, preferiresti garantire che restituisca un valore diverso ad ogni chiamata, giusto? –
Devono essere monotonicamente in aumento? Devono sopportare qualche relazione con il tempo * effettivo *? Devono essere univoci su più percorsi? –