Table des matières
Contenu de la question
Solution
...但我需要单调递增的时间戳!
currenttimemillis
nanotime
问题
Maison Java Pourquoi le temps écoulé calculé sur une grande fenêtre de temps diffère-t-il de plus de 100 millisecondes entre System.currentTimeMillis et System.nanoTime

Pourquoi le temps écoulé calculé sur une grande fenêtre de temps diffère-t-il de plus de 100 millisecondes entre System.currentTimeMillis et System.nanoTime

Feb 09, 2024 am 10:24 AM
overflow

L'éditeur de PHP Apple expliquera pourquoi le temps écoulé calculé sur une grande fenêtre de temps présente une différence allant jusqu'à 100+ millisecondes entre System.currentTimeMillis et System.nanoTime. Ce problème implique le mécanisme sous-jacent du système informatique et la méthode de planification du système d'exploitation. Lors du calcul du temps écoulé, System.currentTimeMillis utilise l'heure de l'horloge murale fournie par le système d'exploitation, tandis que System.nanoTime utilise les cycles d'horloge du processeur. En raison du mécanisme de planification du système d'exploitation et de la nature asynchrone de l'horloge matérielle, ces deux méthodes de synchronisation entraîneront des différences horaires. Les raisons spécifiques et les solutions seront présentées en détail dans les articles suivants.

Contenu de la question

J'essaie de créer un ksuid qui peut effectuer un tri par précession en microsecondes dans la même machine virtuelle, puisque currenttimemillis ne donne qu'une précision en millisecondes, pensez à utiliser currenttimemillis() et nanotime() ensemble pour collecter le premier instant. La différence nanotime est calculé comme le nombre de microsecondes écoulées depuis le premier instant et la valeur commençant au deuxième instant. Utilisez le temps écoulé calculé à partir du nanotime et ajoutez-le aux millisecondes instantanées initiales afin que nous puissions calculer l'époque avec une précision de la microseconde à tout instant après le démarrage de la JVM (le tout dans la même JVM).

//Collection statique des nanotimes et currentmillis initiaux 最终长 inittimenanos = system.nanotime();最终长 inittimemillis = system.currenttimemillis();

//À partir de là, lorsque l'heure actuelle avec une précision de la micro/nanoseconde est requise, calculez le temps écoulé à partir du nanotime et ajoutez les millisecondes écoulées au milliseconde initial, et le temps écoulé restant donne le temps avec une précision de la microseconde

final long elapsednanotime = system.nanotime() - inittimenanos;最终双精度 elapsedmillisfromnanotime = elapsednanos / (1000000.0);

// Augmentation monotone du nombre de millisecondes d'horodatage depuis le démarrage de jvm (époque, nous ne pouvons pas l'appeler époque) final 长计算当前时间millis = inittimemillis + elapsedmillisfromnanotime; final long nanosprecision = elapsednanos % 1000000; //Précision temporelle supplémentaire grâce au nanotime

Envisagez d'utiliser ces valeurs pour générer un ksuid croissant de manière monotone qui se rapproche de l'heure actuelle mais est garanti d'être trié en fonction de l'heure de création au sein de la même machine virtuelle Java, car currenttimemillis ne fournit pas de garantie d'horodatage croissant monotone, envisagez d'utiliser cette approche pour générer approximativement Horodatage croissant de manière monotone de l'horodatage réel (peut varier de quelques millisecondes à moins que des ajustements de seconde intercalaire ne soient apportés à l'heure de l'époque). Le temps écoulé calculé à l'aide de l'époque et du nanotemps devait différer de quelques millisecondes, mais la différence réelle variait très fréquemment, et lorsque j'ai exécuté le test ci-dessous pendant 48 heures, j'ai observé une différence allant jusqu'à 150 millisecondes entre les deux. Dans la plupart des cas, le temps écoulé calculé à l'aide du nanotime est supérieur au temps écoulé calculé à l'aide de currenttimemillis, et les temps observés varient de -2 millisecondes à +150 millisecondes.

final long elapsedmillis = system.currenttimemillis() - inittimemillis; //Temps écoulé en millisecondes depuis system.currenttimemillis() 最终双方差millis = elapsedmillisfromnanotime - elapsedmillis; //Variation du temps écoulé

Est-ce que quelque chose me manque à propos des garanties de timing JVM ? La façon de calculer les horodatages approximatifs croissants de manière monotone est-elle erronée ? (Ceci n'est pas utilisé comme époque réelle dans le système, uniquement pour générer l'uuid qui représente également l'instant d'horodatage approximatif au sein du même jvm).

//Cours test

package org.example;

import java.util.concurrent.TimeUnit;

public class Main {
    public static void main(String[] args) throws Exception {
        final long initTimeNanos = System.nanoTime();
        final long initTimeMillis = System.currentTimeMillis();
        System.out.println("Nanos: " + initTimeNanos);
        System.out.println("Millis: " + initTimeMillis);

        while (true) {
            final long currentNanos = System.nanoTime();
            final long elapsedNanos = currentNanos - initTimeNanos;
            final double elapsedMillisFromNanos = elapsedNanos / 1000000.0;
            final long elapsedMillis = System.currentTimeMillis() - initTimeMillis;
            final double varianceMillis = elapsedMillisFromNanos - elapsedMillis;
            if (Math.abs(varianceMillis) > 1) {
                System.out.printf("\nVariance Observed: %.6f\n", varianceMillis);
                System.out.printf("Elapsed Time: %.6fms (from System.nanoTime)\n", elapsedMillisFromNanos);
                System.out.printf("Elapsed Time: %dms (from System.currentTimeMillis)\n", elapsedMillis);
            }
            if (elapsedMillis > TimeUnit.HOURS.toMillis(48)) {
                break;
            }
            Thread.sleep(5000);
            System.out.print(".");
        }
    }
}
Copier après la connexion

Pourquoi la variance du temps écoulé continue-t-elle de changer ? Quelle est la variance maximale à laquelle nous pouvons nous attendre si la JVM fonctionne en continu pendant un an (n'importe quelle JVM garantit une limite supérieure ou inférieure à ce sujet, testée avec Mac et Windows, Mac a donné une lente augmentation de la variance, Windows était beaucoup plus rapide) ?

Je m'attendrais à ce que le temps écoulé varie de moins de 10 millisecondes et que les changements se produisent moins fréquemment. Mais l'observation réelle est que la variance ne cesse de changer, fluctuant de haut en bas, avec jusqu'à 150 millisecondes observées en 48 heures

Solution

Une explication est le maculage du temps basé sur ntp. Plus généralement, le nanotime et le ctm mesurent des choses complètement différentes et on ne peut pas les mélanger.

nanotime a un point 0 arbitraire (obtenir un nanotime de 0 n'a aucune signification particulière), il n'est donc pas nécessaire de l'appeler du tout autre que de comparer ce qu'il renvoie avec les résultats de différents appels nanotime. le nanotime suit le temps écoulé, c'est tout.

system.ctm obtient l'horloge système. Si vous utilisez posix date 命令或在系统设置中编辑系统的时间设置,则不会影响 nanotime,但会更改 system.ctm, ce qui est renvoyé. ctm est également généralement beaucoup plus lent que le nanotime. ctm a également un 0 bien défini - représentant minuit UTC le 1er janvier 1970.

Question : "Je veux que l'heure actuelle corresponde à l'horloge système avec une précision de la nanoseconde" n'est pas possible sur jvm.

时间涂抹是指某些网络时间守护程序注意到您的系统时钟略有偏差,并且不只是将系统时钟编辑到正确的时间,而是引入了涂抹:假设您比实时时间“提前”了 400 毫秒。 ntp 可以将您的时钟向后设置 400 毫秒,但许多日志记录系统假设 system.ctm 不会向后移动(这是一个不正确但广泛应用的假设)。

这可以通过让时间放慢一段时间来“修复”:每经过 100 毫秒,ntp 守护进程就会将时钟“保持”在同一毫秒上一毫秒。每 100 毫秒就赶上 1 毫秒,因此在 400,000 毫秒(仅 400 秒)内,时钟恢复与网络同步,并且日志记录根本不受影响。

但是,这显然会完全破坏 system.ctm 和 nanotime 之间的任何关系!

大多数 ntp 都是这样涂抹的(它们也会向前涂抹 - 如果您的系统时钟落后,它不仅仅会向前跳跃:这会使日志撒谎(使其看起来就像两个事件之间存在一些间隙)比实际大得多),因此每 100 毫秒,ntp 就会使时钟跳过一毫秒,类似这样的事情,以赶上。

...但我需要单调递增的时间戳!

那么 nanotime 就无关紧要了。不要使用它。

拥有一些提供 id 的集中“商店”。一种实现:

class TimeStore {
  long lastVal = 0L;

  public synchronized long get() {
    long mark = System.currentTimeMillis() << 4;
    return lastVal = Math.max(mark, lastVal + 1);
  }
}
Copier après la connexion

这将返回当前时间,左移 4 位,并将填充此移位“释放”的 16 个值,以便能够在同一时间生成单调递增值,最多 16 次;同一毫秒内的任何进一步请求都会潜入下一毫秒。

尽管如此,这可能并不比nanotime慢。

rzwitserloot的回答是正确的。我将向您提供我对各种问题的看法。

currenttimemillisnanotime 无关

system.currenttimemillissystem.nanotime 彼此无关。

  • currenttimemillis 从主机的硬件时钟单元检索当前日期和时间,由主机操作系统管理。
  • nanotime 来自主机 cpu 保存的计数。

currenttimemillis

所以首先要了解人类的年月日和时分秒的概念。传统计算机中使用的时钟硬件的分辨率有限,有些是毫秒,有些是微秒,但没有纳秒。

由于各种原因,本次通话报告的日期和时间可能会有所不同。其中一个原因是,在电池电量耗尽的情况下启动的计算机会将其时钟重置为默认时刻,直到通过调用时间服务器进行纠正。另一个原因是系统管理员或用户可能会更改日期时间。还有一个原因是硬件时钟可能无法很好地保持时间,并且会通过调用时间服务器在更新之间运行得快或慢。

nanotime

nanotime 调用以纳秒计数形式告知经过的时间。但这个流逝的时间与日历和墙上的时钟无关。此调用仅返回经过的纳秒的单调计数。

这个计数非常准确,因为它来自计算机的“跳动的心脏”。返回的数量始终在增加,直到达到 long.max_value,然后环绕到 long.min_value。这给出了大约 292 年的范围,但这并不意味着从现在起 292 年。计数的起点未指定。在某些 java 实现中,您可能会看到计数在计算机启动时开始。但并不能保证这一点。

问题

您可能会考虑寻找 新 6、7、8 版本 的实现a href="https://en.wikipedia.org/wiki/universally_unique_identifier" rel="nofollow noreferrer">uuid 被提议给 ietf 进行标准化。

currenttimemillis 在现代 java 中已被 java.time.instant 类取代。调用 instant.now 捕获 utc 中的当前时刻。

java 9+ 中的常见实现以微秒为单位报告,但在 java 8 中以毫秒为单位。 instant 类能够以纳秒为单位。

Idée intelligente. Mais ce n'est pas réaliste. Comme mentionné ci-dessus, currenttimemillisnanotime 不相关。最重要的是,currenttimemillis 的结果可能会因多种原因而有所不同。同时,nanotime 计数可能会随着主机的每次启动而变化,并且肯定不会对应于其他计算机上进行的任何 nanotime appelle.

Oui, vous ignorez le fait que la spécification Java ne donne aucune des garanties que vous semblez supposer.

La seule garantie dans

javadoc est que nanotime 是“高分辨率”,至少与 currenttimemillis est aussi bon. Et il n'y a aucune garantie quand on peut s'attendre à la fin de 292.

En même temps, currenttimemillis est une cible mouvante et peut changer à tout moment, avancer ou reculer.

C’est imprévisible.

La spécification Java ne donne aucune garantie de ce type.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Comment déverrouiller tout dans Myrise
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Le prix du Bitcoin depuis sa naissance 2009-2025 Le résumé le plus complet des prix historiques du BTC Le prix du Bitcoin depuis sa naissance 2009-2025 Le résumé le plus complet des prix historiques du BTC Jan 15, 2025 pm 08:11 PM

Depuis sa création en 2009, Bitcoin est devenu un leader dans le monde des cryptomonnaies et son prix a connu d’énormes fluctuations. Pour fournir un aperçu historique complet, cet article compile les données sur les prix du Bitcoin de 2009 à 2025, couvrant les principaux événements du marché, les changements de sentiment du marché et les facteurs importants influençant les mouvements de prix.

Aperçu du prix historique du Bitcoin depuis sa naissance. Collection complète des tendances historiques des prix du Bitcoin. Aperçu du prix historique du Bitcoin depuis sa naissance. Collection complète des tendances historiques des prix du Bitcoin. Jan 15, 2025 pm 08:14 PM

Le Bitcoin, en tant que crypto-monnaie, a connu une volatilité importante sur le marché depuis sa création. Cet article fournira un aperçu du prix historique du Bitcoin depuis sa naissance pour aider les lecteurs à comprendre ses tendances de prix et ses moments clés. En analysant les données historiques sur les prix du Bitcoin, nous pouvons comprendre l'évaluation de sa valeur par le marché, les facteurs affectant ses fluctuations et fournir une base pour les décisions d'investissement futures.

Une liste des prix historiques depuis la naissance du tableau des tendances des prix historiques Bitcoin BTC (dernier résumé) Une liste des prix historiques depuis la naissance du tableau des tendances des prix historiques Bitcoin BTC (dernier résumé) Feb 11, 2025 pm 11:36 PM

Depuis sa création en 2009, le prix de Bitcoin a connu plusieurs fluctuations majeures, passant à 69 044,77 $ en novembre 2021 et tombant à 3191,22 $ en décembre 2018. En décembre 2024, le dernier prix a dépassé 100 204 $.

Le dernier prix du bitcoin en 2018-2024 USD Le dernier prix du bitcoin en 2018-2024 USD Feb 15, 2025 pm 07:12 PM

Prix ​​USD Bitcoin en temps réel Facteurs qui affectent le prix du bitcoin Indicateurs pour prédire les prix des futurs bitcoins Voici quelques informations clés sur le prix du bitcoin en 2018-2024:

Comment personnaliser le symbole de redimensionnement via CSS et le rendre uniforme avec la couleur d'arrière-plan? Comment personnaliser le symbole de redimensionnement via CSS et le rendre uniforme avec la couleur d'arrière-plan? Apr 05, 2025 pm 02:30 PM

La méthode de personnalisation des symboles de redimension dans CSS est unifiée avec des couleurs d'arrière-plan. Dans le développement quotidien, nous rencontrons souvent des situations où nous devons personnaliser les détails de l'interface utilisateur, tels que l'ajustement ...

Comment utiliser l'attribut Clip-Path de CSS pour réaliser l'effet de courbe à 45 degrés du segmenter? Comment utiliser l'attribut Clip-Path de CSS pour réaliser l'effet de courbe à 45 degrés du segmenter? Apr 04, 2025 pm 11:45 PM

Comment réaliser l'effet de courbe à 45 degrés du segmenter? Dans le processus de mise en œuvre du segmentant, comment faire transformer la bordure droite en une courbe de 45 degrés lorsque vous cliquez sur le bouton gauche, et le point ...

La production de pages H5 est-elle un développement frontal? La production de pages H5 est-elle un développement frontal? Apr 05, 2025 pm 11:42 PM

Oui, la production de pages H5 est une méthode de mise en œuvre importante pour le développement frontal, impliquant des technologies de base telles que HTML, CSS et JavaScript. Les développeurs construisent des pages H5 dynamiques et puissantes en combinant intelligemment ces technologies, telles que l'utilisation du & lt; Canvas & gt; Tag pour dessiner des graphiques ou utiliser JavaScript pour contrôler le comportement d'interaction.

Le texte sous la disposition Flex est omis mais le conteneur est ouvert? Comment le résoudre? Le texte sous la disposition Flex est omis mais le conteneur est ouvert? Comment le résoudre? Apr 05, 2025 pm 11:00 PM

Le problème de l'ouverture des conteneurs en raison d'une omission excessive du texte sous disposition flexible et de solutions est utilisé ...