如Java博客文章Beware of System.nanoTime()中所述,在x86系统上,Java的System.nanoTime()使用CPU特定计数器返回时间值.现在考虑以下用于测量呼叫时间的情况:
long time1= System.nanoTime();
foo();
long time2 = System.nanoTime();
long timeSpent = time2-time1;
Run Code Online (Sandbox Code Playgroud)
现在在多核系统中,可能是在测量time1之后,线程被调度到不同的处理器,其计数器小于先前CPU的计数器.因此,我们可以得到time2中的值,该值小于 time1.因此,我们将在timeSpent中得到负值.
考虑到这种情况,是不是System.nanotime现在几乎没用?
我知道改变系统时间不会影响纳米时间.这不是我上面描述的问题.问题是每个CPU都会在打开后保留不同的计数器.与第一个CPU相比,第二个CPU上的计数器可以更低.由于在获取time1之后OS可以将线程调度到第二个CPU,因此timeSpent的值可能不正确甚至是负数.
我知道Thread.sleep()可以让java线程暂停一段时间,比如某些毫秒和某个纳秒.但问题是这个函数的调用也会导致开销.
例如,如果我想要一个线程暂停100纳秒,我调用Thread.sleep(0,100).这个过程的全部成本是invocation_cost + 100 nanosceonds,这可能比我想要的要大得多.我怎么能避免这个问题,实现我的目的呢?
我需要这个的原因是我想离线进行模拟.我描述了任务的执行时间; 现在我想通过在同一时间段内挂起一个线程来模拟这个执行时间.
谢谢!
我想知道转换大纳秒值的最准确方法是毫秒和纳秒,纳秒的上限为999999.目标是结合纳秒和毫秒值以确保最大分辨率可以达到极限给出.这是为了与睡眠/等待方法和一些提供大纳秒值的其他外部库进行比较.
编辑:我的代码现在如下所示:
while (hasNS3Events()) {
long delayNS = getNS3EventTSDelay();
long delayMS = 0;
if (delayNS <= 0) runOneNS3Event();
else {
try {
if (delayNS > 999999) {
delayMS = delayNS / 1000000;
delayNS = delayNS % 1000000;
}
EVTLOCK.wait(delayMS, (int)delayNS);
} catch (InterruptedException e) {
}
}
}
Run Code Online (Sandbox Code Playgroud)
干杯,克里斯
文件System.nanoTime()说明如下(强调我的).
此方法只能用于测量经过的时间,与系统或挂钟时间的任何其他概念无关.返回的值表示纳秒,因为某些固定但是任意时间(可能在将来,因此值可能为负).该方法提供纳秒精度,但不一定是纳秒精度.不保证值的变化频率.
在我看来,这可以用两种不同的方式解释:
上面粗体的句子是指个人返回值.然后,从数值意义上理解精度和准确度.也就是说,精度指的是有效数字的数量 - 截断的位置,精确度是指数字是否正确(如前面的答案 中所述,'精确'和'准确度'之间有什么区别?)
上面粗体的句子指的是方法本身的能力.然后,精确度和准确性将被理解为飞镖类比(http://en.wikipedia.org/wiki/Precision_vs._accuracy#Accuracy_versus_precision:_the_target_analogy).因此,低精度,高精度=>错误的值被高精度地反复击中:想象物理时间静止不动,nanoTime()的连续调用返回相同的数值,但是它与实际经过的时间有关.参考时间通过一些常数偏移.
哪种解释是正确的?我的观点是,解释2意味着使用nanoTime()(通过减去两个返回值)测量时间差将是正确的纳秒(因为测量中的常数误差/偏移将被消除),而解释1将不会不能保证测量之间的一致性,因此不一定意味着高精度的时间差测量.
2013年 4月15日更新: Java 7文档System.nanoTime()已更新,以解决可能与以前的措辞混淆.
返回正在运行的Java虚拟机的高分辨率时间源的当前值,以纳秒为单位.
此方法只能用于测量经过的时间,与系统或挂钟时间的任何其他概念无关.返回的值表示纳秒,因为某些固定但任意的原始时间(可能在将来,因此值可能为负).在Java虚拟机的实例中,此方法的所有调用都使用相同的原点; 其他虚拟机实例可能使用不同的来源.
这种方法提供纳秒级精度,但不一定是纳秒级分辨率(即,值的变化频率) - 除了分辨率至少与分辨率一样好之外,不做任何保证
currentTimeMillis().跨越大于约292年(2 63纳秒)的连续调用的差异将无法正确计算由于数值溢出而导致的经过时间.
仅当计算在Java虚拟机的同一实例中获得的两个此类值之间的差异时,此方法返回的值才有意义.
Java 8的java.time.Instant以"纳秒分辨率"存储,但使用Instant.now()只提供毫秒分辨率......
Instant instant = Instant.now();
System.out.println(instant);
System.out.println(instant.getNano());
Run Code Online (Sandbox Code Playgroud)
结果...
2013-12-19T18:22:39.639Z
639000000
Run Code Online (Sandbox Code Playgroud)
我怎样才能获得一个"现在"值但具有纳秒分辨率的瞬间?
这个标题几乎是不言自明的,我正在为这种简单而自杀.
看着这里,但没什么用处.
我正在尝试使用以下代码System.nanoTime()来测量代码的已用时间.
public static void main(String[] args) throws Exception {
while (true) {
long start = System.nanoTime();
for (int i = 0; i < 10000; i++)
;
long end = System.nanoTime();
long cost = end - start;
if (cost < 0) {
System.out.println("start: " + start + ", end: " + end + ", cost: " + cost);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我得到了这样的结果:
start: 34571588742886, end: 34571585695366, cost: -3047520
start: 34571590239323, end: 34571586847711, cost: -3391612
start: 34571651240343, end: 34571648928369, cost: …Run Code Online (Sandbox Code Playgroud) 我的应用程序使用android 4.4.X中引入的步进检测器传感器API在后台步骤计数中执行.
我的应用程序必须知道每个步骤事件产生的确切时间(至少准确度为一秒).
因为我执行传感器批处理,所以onSensorChanged(SensorEvent event)调用的时间与步骤事件发生的时间不同 - 我必须使用该event.timestamp字段来获取事件时间.
有关此字段的文档是:
事件发生的纳秒时间
问题:
在某些设备(例如Moto X 2013)中,这个时间戳似乎是自启动以来的纳秒时间,而在某些设备(例如Nexus 5)中,它实际上以纳秒为单位返回通用系统时间System.currentTimeMills() / 1000.
据我所知,关于这一点已经存在一个陈旧的问题,但是由于引入了传感器批处理 - 使用该字段来了解事件时间变得非常重要,并且不可能再依赖于System.currentTimeMills()
我的问题:
我该怎么做才能在所有设备上始终以系统毫秒为单位获取事件时间?
所以我的问题更为笼统.我有以下简单的代码:
for(int i=0;i<10;i++){
long starttime=System.nanoTime();
System.out.println("test");
long runtime=System.nanoTime()-starttime;
System.out.println(i + ":" +"runtime="+runtime);
}
Run Code Online (Sandbox Code Playgroud)
我收到以下输出:
test
0:runtime=153956
test
1:runtime=15396
test
2:runtime=22860
test
3:runtime=11197
test
4:runtime=11197
test
5:runtime=12129
test
6:runtime=11663
test
7:runtime=11664
test
8:runtime=53185
test
9:runtime=12130
Run Code Online (Sandbox Code Playgroud)
第一个和第二个运行时区别的原因是什么?提前感谢=)