System.currentTimeMillis和System.nanoTime

精度与 精确

我想知道的是在更新对象在游戏中的位置时应该使用System.currentTimeMillis()仍是System.nanoTime() ? 他们的运动变化与自上次通话以来通过的时间成正比,我想尽量地精确。 性能

我了解到,不一样的操做系统之间存在一些严重的时间分辨率问题(即Mac / Linux的分辨率几乎为1毫秒,而Windows的分辨率为50毫秒?)。 我主要是在Windows上运行个人应用,而50ms的分辨率彷佛很是不许确。 spa

是否有比我列出的两个更好的选择? 操作系统

有什么建议/意见吗? code


#1楼

这里的一件事是nanoTime方法的不一致。对于相同的输入,它不会给出很是一致的值。currentTimeMillis在性能和一致性方面要好得多,而且尽管不如nanoTime精确,但偏差范围较小,所以其值的准确性更高。 所以,我建议您使用currentTimeMillis 对象


#2楼

就像其余人所说的,currentTimeMillis是时钟时间,因为夏时制,用户更改时间设置,leap秒和互联网时间同步而改变。 若是您的应用依赖于单调增长的通过时间值,则您可能更喜欢nanoTime。 游戏

您可能会认为玩家不会在游戏过程当中摆弄时间设置,也许您是对的。 可是,请不要低估因为Internet时间同步或远程桌面用户形成的中断。 nanoTime API不受这种破坏的影响。 开发

若是要使用时钟时间,但要避免因为Internet时间同步而致使中断,则能够考虑使用NTP客户端(例如Meinberg),该客户端能够将时钟速率“调整”为零,而不只仅是按期重置时钟。 文档

我是根据我的经验讲的。 在我开发的天气应用程序中,我获得了随机出现的风速峰值。 我花了一段时间才意识到典型的PC上的时钟时间行为干扰了个人时基。 当我开始使用nanoTime时,我全部的问题都消失了。 一致性(单调性)对个人应用程序比原始精度或绝对精度更重要。 get


#3楼

若是你只是在寻找的通过时间很是精确的测量,使用System.nanoTime() System.currentTimeMillis()将为您提供自该纪元以来最精确的通过时间(以毫秒为单位System.nanoTime() ,可是System.nanoTime()为您提供相对于某个任意点的纳秒级精确时间。 同步

从Java文档中:

public static long nanoTime()

返回最精确的可用系统计时器的当前值(以纳秒为单位)。

此方法只能用于测量通过时间,而且与系统或挂钟时间的任何其余概念无关。 返回的值表示自某个固定但任意的原始时间以来的纳秒(也许是未来的时间,所以值可能为负)。 此方法提供纳秒精度,但不必定提供纳秒精度。 不能保证值更改的频率。 因为数值溢出,跨越大约292年(2 63纳秒)的连续呼叫中的差别将没法准确计算通过的时间。

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

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

另请参阅: JavaDoc System.nanoTime()JavaDoc System.currentTimeMillis()了解更多信息。


#4楼

较早的JVM不支持System.nanoTime() 。 若是这是一个问题,请坚持使用currentTimeMillis

关于准确性,您几乎是正确的。 在某些Windows计算机上, currentTimeMillis()的分辨率约为10毫秒(而非50毫秒)。 我不肯定为何,可是某些Windows机器和Linux机器同样准确。

我过去使用GAGETimer取得了必定的成功。


#5楼

是的,若是须要这种精度,请使用System.nanoTime() ,可是请注意,您那时须要Java 5+ JVM。

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

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)); }
    }
相关文章
相关标签/搜索