系统。currentTimeMillis vs系统。nanoTime
-
20-08-2019 - |
题
精确度Vs。精密
我想知道的是我是否应该使用 系统。currentTimeMillis() 或 系统。nanoTime() 在更新我的对象的位置在我的游戏吗?他们的变化中的运动是直接成比例的经过时间以来的最后一个电话我想要的是尽可能准确.
我已经阅读,有一些严重的时间分辨率的问题之间不同的操作系统(即Mac/Linux具有几乎1ms决议的同时,窗户有50毫秒的决议??).我主要的运行我的应用程序,在windows和50毫秒的决议似乎很不准确的。
是否有更好的选择比两个我?
任何建议/评论?
解决方案
如果你只是在寻找的经过时间后,使用System.nanoTime()
的非常精确的测量。 System.currentTimeMillis()
会给你在从epoch毫秒最准确的可能经过的时间,但System.nanoTime()
给你一个纳秒精确的时间,相对于某些任意点。
从Java文档:
public static long nanoTime()
返回最准确的可用系统计时器的当前值,在纳秒。
此方法只能用于 测量经过时间,不 涉及到系统中的其他概念 或挂钟时间。返回值 代表,因为有些纳秒 固定但任意的时间(也许在 未来,所以值可能是 负)。这种方法提供 纳秒的精度,但不 一定纳秒的精度。没有 担保是对如何 频繁值的变化。差异 在跨越更大的连续调用 大于约292年(2 63 毫微秒)不会准确 计算由于数值经过时间 溢出。
例如,为了测量一些代码需要多长时间来执行:
long startTime = System.nanoTime();
// ... the code being measured ...
long estimatedTime = System.nanoTime() - startTime;
参见: JavaDoc的系统。 nanoTime()和的JavaDoc System.currentTimeMillis的()获得更多信息。
其他提示
由于没有其他人提及的本...
是不安全比较不同线程之间System.nanoTime()
调用的结果。即使线程的事件以可预测的顺序发生,以纳秒为单位的差异可以是正的或负的。
System.currentTimeMillis()
为线程之间安全使用。
更新由长Arkadiy :我在甲骨文的Java 8的时间观察到在Windows 7上System.currentTimeMillis()
的更正确的行为用1毫秒精度返回。在OpenJDK的源代码并没有改变,所以我不知道是什么原因导致了更好的性能。
孙大卫霍姆斯发布了博客文章一对夫妇多年前有在Java的定时API的一个非常详细的研究(特别是System.currentTimeMillis()
和System.nanoTime()
),当你想使用的,以及它们如何在内部工作。
里面的热点VM:时钟,定时器和调度活动 - 第一部分 - 视窗
在Windows上使用Java进行有一个定时参数的API定时器的一个非常有趣的方面是,计时器的分辨率可以根据可能已经做出什么其他的API调用改变 - 系统范围内(不只是在特定的过程)。他示出了其中使用Thread.sleep()
将导致此分辨率变更的例子。
System.nanoTime()
不能在较早的JVM支持。如果这是一个问题,坚持使用currentTimeMillis
关于准确性,你几乎是正确的。在某些Windows机器,currentTimeMillis()
具有10ms左右(不50ms的)决议。我不知道为什么,但是一些Windows机器是一样的Linux机器一样精确。
我已经使用 GAGETimer 在中度成功过去。
正如其他人所说,的currentTimeMillis是时钟时间,从而改变由于夏令时,用户改变时间设置,闰秒,和网络时间同步。如果您的应用程序依赖于单调递增经过时间值,你可能更喜欢nanoTime代替。
您可能会认为球员们不会随着时间的设置,在游戏过程中摆弄,也许你是对的。可别小看中断,由于网络时间同步,或者是远程桌面用户。该nanoTime API不受这种破坏。
如果你想使用的时钟时间,但要避免由于网络时间同步的不连续性,你可能会考虑一个NTP客户端,如Meinberg,时钟速率,以零它其中“曲调”,而不只是定期重新设定时钟。
我从个人的经验发言。在我开发了一个天气应用程序,我得到随机出现的风速峰值。过了好一会儿,我意识到,我的时基正在通过的时钟时间一个典型的PC机上的行为打乱了。当我开始使用nanoTime我所有的问题就消失了。一致性(单调)是我的应用程序比生吃精度或绝对精度更重要。
是,如果这样的精度要求使用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)); }
}
我已经与 nanotime 很好的经验。它提供挂钟时间为两个长整型(秒因为内的第二历元和毫微秒),使用JNI库。它可提供预编译的Windows和Linux的JNI部分。
对于游戏的图形和顺利地位的更新,使用 System.nanoTime()
而不是 System.currentTimeMillis()
.我从currentTimeMillis()以nanoTime()中的一个游戏了一些主要改进是在平滑运动。
虽然一毫秒可能看起来好像它应该已经精确,在视觉上不是。因素 nanoTime()
可以改进包括:
- 准确定位素下面的墙壁钟的决议
- 能力抗别之间的像素,如果你想要的
- 窗户墙时不准确
- 时钟跳动(不一致的时壁钟实际上蜱前)
其他答复建议,nanoTime没有性能的成本,如果所谓的反复--这将是最好的称呼它只是一旦每框架,并使用相同的价值计算的整个框架。
System.currentTimeMillis()
不是经过时间的安全,因为这个方法是将系统的系统实时时钟变化敏感。
您应该使用System.nanoTime
。
请参考Java系统的帮助:
关于nanoTime方法:
..此方法提供纳秒的精度,但不一定 纳秒级分辨率(即频率变化值) - 无 担保除了分辨率至少一样好做 那的currentTimeMillis()的..
如果您使用System.currentTimeMillis()
你经过的时间可以是负数(返回< - 未来)
在这里有一点是nanoTime method.it的不一致性为同一input.currentTimeMillis没有给出非常一致的值不会在性能和一致性,同时也方面要好得多,虽然不是那样精确,nanoTime,具有较低误差的余量,并在其值因此更准确度。因此,我建议你使用的currentTimeMillis