关于java:System.currentTimeMillis vs System.nanoTime

System.currentTimeMillis vs System.nanoTime

精度与精度

我想知道在更新我的对象在我的游戏中的位置时是应该使用System.CurrentTimeMillis()还是System.NanoTime()?它们在移动上的变化与上次调用以来所用的时间成正比,我希望尽可能精确。

我读到过不同操作系统之间存在一些严重的时间分辨率问题(即Mac/Linux的分辨率接近1 ms,而Windows的分辨率为50 ms)??)我主要是在Windows上运行我的应用程序,50毫秒的分辨率似乎相当不准确。

有比我列出的两个更好的选择吗?

有什么建议/意见吗?


如果您只是在寻找非常精确的经过时间测量值,请使用System.nanoTime()System.currentTimeMillis()将以毫秒为单位提供最精确的时间,但相对于任意点,System.nanoTime()将以纳秒为单位提供精确的时间。

来自Java文档:

1
public static long nanoTime()

Returns the current value of the most precise available system timer, in nanoseconds.

This method can only be used to
measure elapsed time and is not
related to any other notion of system
or wall-clock time. The value returned
represents nanoseconds since some
fixed but arbitrary time (perhaps in
the future, so values may be
negative). This method provides
nanosecond precision, but not
necessarily nanosecond accuracy. No
guarantees are made about how
frequently values change. Differences
in successive calls that span greater
than approximately 292 years (263
nanoseconds) will not accurately
compute elapsed time due to numerical
overflow.

例如,要测量执行某些代码所需的时间:

1
2
3
long startTime = System.nanoTime();    
// ... the code being measured ...    
long estimatedTime = System.nanoTime() - startTime;

另请参见:javadoc system.nantime()和javadoc system.currentTimeMillis()以获取更多信息。


因为没人提到这件事…

比较不同线程之间的System.nanoTime()调用的结果是不安全的。即使线程的事件以可预测的顺序发生,纳秒的差异也可以是正的或负的。

System.currentTimeMillis()在螺纹之间使用是安全的。


ARKADYY更新:在Oracle Java 8中,我在Windows 7上观察到了EDOCX1 1的更正确的行为。返回的时间精度为1毫秒。OpenJDK中的源代码没有更改,所以我不知道是什么导致了更好的行为。

Sun的大卫.福尔摩斯在几年前发布了一篇博客文章,详细介绍了Java定时API(特别是EDCOX1 1和EDCOX1 0),当你想使用它时,以及它们是如何在内部工作的。

热点虚拟机内部:时钟、计时器和调度事件-第一部分-窗口

Java在API上使用的计时器的一个非常有趣的方面是,具有定时等待参数的API是,定时器的分辨率可以根据其他API调用可能做出的变化-系统范围(不只是在特定的进程中)。他举了一个例子,使用Thread.sleep()将导致此解决方案的更改。


旧的JVM不支持System.nanoTime()。如果这是一个问题,请坚持使用currentTimeMillis

关于准确性,你几乎是正确的。在一些Windows机器上,currentTimeMillis()的分辨率约为10毫秒(而不是50毫秒)。我不知道为什么,但有些Windows机器和Linux机器一样精确。

我以前用过gagetimer,但效果一般。


有人说的,当前的时间是一个时钟的时间的变化,由于变化的夏令时间,用户时间的设置,时间跳跃秒,与网络同步。如果你的应用程序运行时间的时间值取决于在线单调增加,你会选择nanotime相反。

你可能认为该球员不会被设置在lipelling团队的游戏,也许你是对的。别underestimate中断导致的网络时间同步,或可能的远程桌面用户。在这nanotime API是一种有效的免疫。

如果你想使用的时钟的时间,但由于Internet时间同步,避免discontinuities,你可能认为一个NTP客户端如迈恩伯格"曲调,"它在零的时钟速率的时钟,而不是只是resetting定期。

我说,从个人的经验。在应用程序开发的天气我是随机发生的,我要刺风速度。这是当我意识到了我的timebase被破坏的行为是典型的PC机上的时钟的时间,当我消失了我所有的问题。nanotime入门使用。更重要的是一致性(单调性)或不到我的应用程序的原始精度绝对精度。


是的,如果需要这样的精度,使用EDCOX1×0 },但是请注意,您需要Java 5 +JVM。

在我的XP系统上,我看到系统时间报告至少为100微秒278纳秒,使用以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void test() {
    System.out.println("currentTimeMillis:"+System.currentTimeMillis());
    System.out.println("nanoTime         :"+System.nanoTime());
    System.out.println();

    testNano(false);                                                            // to sync with currentTimeMillis() timer tick
    for(int xa=0; xa<10; xa++) {
        testNano(true);
        }
    }

private void testNano(boolean shw) {
    long strMS=System.currentTimeMillis();
    long strNS=System.nanoTime();
    long curMS;
    while((curMS=System.currentTimeMillis()) == strMS) {
        if(shw) { System.out.println("Nano:"+(System.nanoTime()-strNS)); }
        }
    if(shw) { System.out.println("Nano:"+(System.nanoTime()-strNS)+", Milli:"+(curMS-strMS)); }
    }


游戏图形是&;光滑的位置更新,而不是使用System.nanoTime()System.currentTimeMillis()。开关从当前的时间(一)至(nanotime)在游戏中的主要改进了视觉和运动的平滑度。

在一个millisecond可能似乎是需要的,它应该已经visually,它不是。可以提高的因素有:nanoTime()

  • 准确的定位在像素分辨率的壁钟
  • 抗混叠能力之间的像素,如果你想
  • Windows inaccuracy壁钟
  • 时钟抖动的时钟不一致时前墙附近的蜱)

其他回答suggest的性能,并有一个nanotime成本if(repeatedly -它只是将是最好的一次呼叫的每帧,计算和使用的相同的值的整个框架。


我在纳米时间方面有很好的经验。它使用一个JNI库提供两个长的壁钟时间(从纪元开始的秒数和该秒内的纳秒数)。它可以与预编译的JNI部分一起使用,适用于Windows和Linux。


System.currentTimeMillis()运行时间的时间是不安全的,因为这种方法是敏感的系统是一个实时的系统时钟的变化。你应该使用System.nanoTime。请参考:Java系统的帮助

方法:我们nanotime

.. This method provides nanosecond precision, but not necessarily
nanosecond resolution (that is, how frequently the value changes) - no
guarantees are made except that the resolution is at least as good as
that of currentTimeMillis()..

如果你使用你的运行时间的时间可以System.currentTimeMillis()负(背<——未来)


这里的一个问题是纳米时间方法的不一致性。它不能为相同的输入提供非常一致的值。在性能和一致性方面,CurrentTimeMillis做得更好,而且,尽管不如纳米时间精确,但其误差范围较低,因此其值的准确性更高。因此,我建议您使用currentTimeMillis