Dal momento che Java 7, System.nanoTime()
è garantito per essere sicuro dalle specifiche JDK. System.nanoTime()
Javadoc chiarisce che tutte le invocazioni osservate all'interno di una JVM (ovvero attraverso tutti i thread) sono monotoniche:
Il valore restituito rappresenta i nanosecondi da un tempo di origine fisso ma arbitrario (forse in futuro, quindi i valori possono essere negativi). La stessa origine viene utilizzata da tutte le invocazioni di questo metodo in un'istanza di una macchina virtuale Java; è probabile che altre istanze di macchine virtuali utilizzino un'origine diversa.
L'implementazione di JVM / JDK è responsabile della risoluzione delle incoerenze che potrebbero essere osservate quando vengono chiamate le utility del sistema operativo sottostante (ad esempio quelle menzionate nella risposta di Tom Anderson ).
La maggior parte delle altre vecchie risposte a questa domanda (scritta nel 2009-2012) esprime FUD che probabilmente era rilevante per Java 5 o Java 6 ma non è più rilevante per le versioni moderne di Java.
Vale la pena ricordare, tuttavia, che nonostante nanoTime()
la sicurezza di JDK , ci sono stati diversi bug in OpenJDK che lo hanno impedito di mantenere questa garanzia su determinate piattaforme o in determinate circostanze (ad esempio JDK-8040140 , JDK-8184271 ). Non ci sono bug aperti (conosciuti) in OpenJDK wrtnanoTime()
, ma la scoperta di un nuovo bug o una regressione in una nuova versione di OpenJDK non dovrebbe scioccare nessuno.
Tenendo presente ciò, il codice che utilizza nanoTime()
per il blocco temporizzato, l'intervallo di attesa, i timeout, ecc. Dovrebbe preferibilmente trattare le differenze di tempo negative (timeout) come zeri piuttosto che generare eccezioni. Questa pratica è anche preferibile perché è coerente con il comportamento di tutti i metodi attesa temporizzata in tutte le classi java.util.concurrent.*
, ad esempio Semaphore.tryAcquire()
, Lock.tryLock()
, BlockingQueue.poll()
, etc.
Tuttavia, nanoTime()
dovrebbe essere ancora preferito per l'implementazione di blocchi temporizzati, intervalli di attesa, timeout, ecc. currentTimeMillis()
Perché quest'ultimo è soggetto al fenomeno del "tempo che va indietro" (ad esempio a causa della correzione del tempo del server), cioè currentTimeMillis()
non è adatto per misurare gli intervalli di tempo affatto. Vedi questa risposta per maggiori informazioni.
Invece di utilizzare nanoTime()
direttamente per le misurazioni del tempo di esecuzione del codice, è preferibile utilizzare strutture di benchmarking e profilatori specializzati, ad esempio JMH e async-profiler in modalità di profilatura dell'orologio da parete .