System.currentTimeMillis和System.nanoTime

三世轮回 提交于 2020-02-27 20:27:41

精度与 精确

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

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

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

有什么建议/意见吗?


#1楼

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


#2楼

就像其他人所说的,currentTimeMillis是时钟时间,由于夏时制,用户更改时间设置,leap秒和互联网时间同步而改变。 如果您的应用依赖于单调增加的经过时间值,则您可能更喜欢nanoTime。

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

如果要使用时钟时间,但要避免由于Internet时间同步而导致中断,则可以考虑使用NTP客户端(例如Meinberg),该客户端可以将时钟速率“调整”为零,而不仅仅是定期重置时钟。

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


#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)); }
    }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!