如何在 java 中获取以纳秒为单位的当前时间?

How to get current time in nano seconds in java?

我做了很多研究,但没有找到任何好的答案。 我想以纳秒为单位获取当前日期和时间。 我发现 System.nanoTime() 将提供纳秒,但那是系统经过的时间。意味着它将提供系统启动的时间。我需要以纳秒为单位使用当前日期和时间。

我需要这个来避免 InfluxDB 中的点重复,请参阅 How does InfluxDB handle duplicate points? 所以当我使用毫秒时,我面临数据联合的问题。因此需要决定使用纳秒,但问题是使用 System.nanoTime() 生成纳秒时不包含当前日期和时间数据。它给了我 JVM 正常运行时间,这对我来说没用。

您可以获得 Java 可以从 Instant.now() 中获得的最佳准确度和精确度。这是否足以解决你的问题,我不敢说。当然,在普通计算机上,无法获得纳秒级精度。

如果 Instant.now() returns 相同的值两次,您可能需要玩一些技巧,添加一个人造纳秒。

或者简单地使用your link中提到的技巧:

Introduce an arbitrary new tag to enforce uniqueness.

对于添加人工纳秒的技巧,您可以使用以下内容:

public class TimeProvider {

    Instant last = Instant.now().minusSeconds(1);

    Instant getUniqueInstant() {
        Instant result = Instant.now();
        if (! result.isAfter(last)) {
            result = last.plusNanos(1);
        }
        last = result;
        return result;
    }
}

当我在我的计算机上从这个 class 快速连续绘制时间时,我得到如下结果。从输出(我解释它的方式)看来:

  • 我的 JVM 无法从系统时钟获得高于微秒(秒的 6 位小数)的精度。
  • 不时添加一个人工纳秒以保持瞬间的唯一性。

.

2018-08-29T15:18:35.617616001Z
2018-08-29T15:18:35.617617Z
2018-08-29T15:18:35.617618Z
2018-08-29T15:18:35.617618001Z
2018-08-29T15:18:35.617619Z
2018-08-29T15:18:35.617619001Z
2018-08-29T15:18:35.617620Z
2018-08-29T15:18:35.617620001Z
2018-08-29T15:18:35.617621Z
2018-08-29T15:18:35.617621001Z
2018-08-29T15:18:35.617622Z
2018-08-29T15:18:35.617623Z
2018-08-29T15:18:35.617623001Z
2018-08-29T15:18:35.617624Z
2018-08-29T15:18:35.617624001Z
2018-08-29T15:18:35.617625Z
2018-08-29T15:18:35.617625001Z
2018-08-29T15:18:35.617626Z
2018-08-29T15:18:35.617626001Z
2018-08-29T15:18:35.617627Z
2018-08-29T15:18:35.617627001Z
2018-08-29T15:18:35.617628Z
2018-08-29T15:18:35.617631Z
2018-08-29T15:18:35.617634Z
2018-08-29T15:18:35.617635Z
2018-08-29T15:18:35.617636Z
2018-08-29T15:18:35.617636001Z
2018-08-29T15:18:35.617637Z
2018-08-29T15:18:35.617637001Z
2018-08-29T15:18:35.617638Z

理论上,可以得到“优于微秒”精度的当前时间如下:

Clock clock = Clock.systemDefaultZone();
Instant instant = clock.instant();   // or Instant.now();
long seconds = instant.getEpochSecond();
long nano = instant.getNano();
// epoch nanoseconds = seconds * 10E9 + nano

问题:

  1. systemDefaultZone() 调用为平台提供“最佳可用时钟”。 JVM 规范说这可能比毫秒精度更好,但这并不能保证。所以 nano 值可能不会比毫秒精度更好。

  2. seconds和nano的取值取决于本地硬件时钟的精度。在许多系统上,保持本地时钟与“实时”时间同步是很困难的。通常,亚毫秒级精度具有挑战性,而表面上的纳秒级精度是一种错觉。

  3. 即使您之前设法将硬件时钟与“实时”时间源同步到纳秒精度,进行上述调用以获取纪元纳秒时间的开销和可变性也会破坏纳秒准确性。 (诸如内存缓存可变性、主内存总线的繁忙程度等。当然,本地硬件时钟自上次同步以来可能已经发生漂移。)

实际上,在大多数系统上,纳秒级精度是无法实现的,因此您需要避免依赖于此的设计/算法。

最后,感谢 Franz Wilhelmstötter 先生

我找到了一种解决方案。使用 http://jenetics.io/ 和 Class call NanoClock.java 正在转换并执行 Stephen C 建议的相同技巧。我想分享这个,因为它对其他人也很有用。我无法确认是否给出了精确的纳米时间,但这个技巧对我有用。 @Ole V.V。再次感谢您的帮助。