Depuis Java 7, la System.nanoTime()
sécurité est garantie par la spécification JDK. System.nanoTime()
Javadoc indique clairement que toutes les invocations observées dans une JVM (c'est-à-dire sur tous les threads) sont monotones:
La valeur renvoyée représente des nanosecondes depuis une heure d'origine fixe mais arbitraire (peut-être dans le futur, les valeurs peuvent donc être négatives). La même origine est utilisée par toutes les invocations de cette méthode dans une instance d'une machine virtuelle Java; d'autres instances de machine virtuelle utiliseront probablement une origine différente.
L'implémentation JVM / JDK est responsable de l'aplanissement des incohérences qui pourraient être observées lorsque les utilitaires du système d'exploitation sous-jacents sont appelés (par exemple ceux mentionnés dans la réponse de Tom Anderson ).
La majorité des autres anciennes réponses à cette question (écrites en 2009-2012) expriment un FUD qui était probablement pertinent pour Java 5 ou Java 6 mais qui n'est plus pertinent pour les versions modernes de Java.
Il convient cependant de mentionner que malgré nanoTime()
la sécurité des garanties JDK , il y a eu plusieurs bogues dans OpenJDK qui l'empêchent de respecter cette garantie sur certaines plates-formes ou dans certaines circonstances (par exemple JDK-8040140 , JDK-8184271 ). Il n'y a pas de bogue ouvert (connu) dans OpenJDK nanoTime()
pour le moment, mais la découverte d'un nouveau bogue ou une régression dans une nouvelle version d'OpenJDK ne devrait choquer personne.
Dans cet esprit, le code qui utilise nanoTime()
pour le blocage temporisé, l'attente d'intervalle, les délais d'attente, etc. devrait de préférence traiter les différences de temps négatives (délais d'attente) comme des zéros plutôt que de lever des exceptions. Cette pratique est également préférable , car il est compatible avec le comportement de toutes les méthodes chronométrées d'attente dans toutes les classes java.util.concurrent.*
, par exemple Semaphore.tryAcquire()
, Lock.tryLock()
, BlockingQueue.poll()
, etc.
Néanmoins, il nanoTime()
faut toujours préférer pour mettre en œuvre le blocage temporisé, l'attente d'intervalle, les délais d'attente, etc. à currentTimeMillis()
parce que ce dernier est sujet au phénomène de «retour en arrière» (par exemple en raison de la correction de l'heure du serveur), c'est currentTimeMillis()
-à- dire qu'il n'est pas adapté à la mesure des intervalles de temps du tout. Voir cette réponse pour plus d'informations.
Au lieu d'utiliser nanoTime()
directement pour les mesures de temps d'exécution du code, des cadres d'analyse comparative et des profileurs spécialisés devraient de préférence être utilisés, par exemple JMH et async-profiler en mode de profilage d'horloge murale .