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