Поскольку Java 7, System.nanoTime()
гарантированно безопасен в соответствии со спецификацией JDK. System.nanoTime()
Javadoc дает понять, что все наблюдаемые вызовы в JVM (то есть , по всем потокам) монотонны:
Возвращаемое значение представляет наносекунды с некоторого фиксированного, но произвольного времени начала (возможно, в будущем, поэтому значения могут быть отрицательными). Один и тот же источник используется всеми вызовами этого метода в экземпляре виртуальной машины Java; другие экземпляры виртуальной машины могут использовать другое происхождение.
Реализация JVM / JDK отвечает за устранение несоответствий, которые могут наблюдаться при вызове базовых утилит ОС (например, упомянутых в Тома Андерсона ).
Большинство других старых ответов на этот вопрос (написано в 2009 - 2012) выражают FUD, который, вероятно, имел отношение к Java 5 или Java 6, но больше не относится к современным версиям Java.
Однако стоит отметить, что, несмотря на то, что JDK гарантирует безопасность nanoTime()
, в OpenJDK было несколько ошибок, из-за которых он не поддерживал эту гарантию на определенных платформах или при определенных обстоятельствах (например, JDK-8040140 , JDK-8184271 ). На данный момент в OpenJDK нет открытых (известных) ошибок по nanoTime()
, но обнаружение новой такой ошибки или регрессия в новой версии OpenJDK никого не должно шокировать.
Имея это в виду, код , который использует nanoTime()
для временной блокировки, ожидания интервала, тайм-аутов и т. Д., Предпочтительно должен рассматривать отрицательные различия во времени (тайм-ауты) как нули, а не как исключения исключения. также предпочтительнее, поскольку это согласуется с поведением всех методов ожидания по времени во всех классах в java.util.concurrent.*
, например Semaphore.tryAcquire()
, Lock.tryLock()
, BlockingQueue.poll()
и т. д.
Тем не менее, nanoTime()
по-прежнему предпочтительнее для реализации временной блокировки, интервала ожидания, тайм-аутов и т. Д. До currentTimeMillis()
, потому что последний подвержен явлению "время идет назад" (например, из-за коррекции времени сервера) я е. currentTimeMillis()
вообще не подходит для измерения временных интервалов. См. этот ответ для получения дополнительной информации.
Вместо использования nanoTime()
для непосредственного измерения времени выполнения кода предпочтительно использовать специализированные платформы и профилировщики, например JMH и асинхронный профилировщик в стене режим профилирования часов .