Desde o Java 7, System.nanoTime()
é garantido que seja seguro pela especificação JDK. System.nanoTime()
O Javadoc deixa claro que todas as invocações observadas em uma JVM (ou seja, em todos os threads) são monotônicas:
O valor retornado representa nanossegundos desde algum tempo de origem fixo, mas arbitrário (talvez no futuro, portanto, os valores podem ser negativos). A mesma origem é usada por todas as chamadas deste método em uma instância de uma máquina virtual Java; outras instâncias de máquina virtual provavelmente usarão uma origem diferente.
A implementação da JVM / JDK é responsável por resolver as inconsistências que podem ser observadas quando os utilitários do SO subjacente são chamados (por exemplo, os mencionados na resposta de Tom Anderson ).
A maioria das outras respostas antigas para essa pergunta (escritas em 2009–2012) expressa FUD que provavelmente era relevante para Java 5 ou Java 6, mas não é mais relevante para versões modernas de Java.
Vale ressaltar, no entanto, que, apesar da segurança nanoTime()
das garantias do JDK , houve vários bugs no OpenJDK, impedindo essa garantia em determinadas plataformas ou sob certas circunstâncias (por exemplo, JDK-8040140 , JDK-8184271 ). Não há bugs abertos (conhecidos) no OpenJDK wrtnanoTime()
, mas a descoberta de um novo bug ou uma regressão em uma versão mais recente do OpenJDK não deve chocar ninguém.
Com isso em mente, o código usado nanoTime()
para bloqueio cronometrado, espera em intervalos, tempos limite, etc. deve preferencialmente tratar diferenças de tempo negativas (tempos limite) como zeros, em vez de lançar exceções. Esta prática é também preferível porque é consistente com o comportamento de todos os métodos de espera temporizada em todas as classes em java.util.concurrent.*
, por exemplo Semaphore.tryAcquire()
, Lock.tryLock()
, BlockingQueue.poll()
, etc.
No entanto, nanoTime()
ainda deve ser preferido para a implementação de bloqueio cronometrado, intervalo de espera, tempo limite, etc., currentTimeMillis()
porque este último está sujeito ao fenômeno "tempo atrasado" (por exemplo, devido à correção da hora do servidor), ou currentTimeMillis()
seja, não é adequado para medir intervalos de tempo em absoluto. Veja esta resposta para mais informações.
Em vez de usar nanoTime()
diretamente para medições de tempo de execução de código, estruturas e perfis de benchmarking especializados devem ser usados preferencialmente, por exemplo, JMH e async-profiler no modo de criação de perfil de relógio de parede .