如何从两个nanoTime对象相减中得到有意义的结果?该问题涉及IT技术。

16

我创建了一个过滤器来监控请求的长度。

long start = System.nanoTime();

...

long end = System.nanoTime();

我该如何从现在开始计算得到毫秒数?

6个回答

51
(end - start) / 1000000

1微秒=1000纳秒

1毫秒=1000微秒

请注意,结果将向下舍入,但通常你也无法获得真正的纳秒精度(精度取决于操作系统)。从nanoTime()的Javadoc中可以了解到:

该方法提供纳秒级精度,但不一定具有纳秒级准确性。


7
以防万一……“Precision”大致意味着小数位数(数字1.00000000000135738具有很高的精度),而“accuracy”则表示这些小数位数有多少是正确的。例如,精度为0.01的1.0001可以在1.0101和0.9901之间任何一个值,而精度为0.000001的1.0则保证位于0.000009和1.000001之间的某个位置。 - Michael Clerx
2
这个程序可以工作,但是它返回的数字像10或5,而不是10.234234234之类的。我需要进行强制类型转换吗? - Blankman
1
@Blankman: 如果你想得到一个像10.234234234这样的数字,可以使用(end - start) / (double) 1000000(或者如果你想要浮点数,可以使用(end - start) / 1000000. 或者(end - start) / (float) 1000000 - Chris Lercher
溢出问题怎么办?System.nanoTime是否保证不会发生溢出? - big lep
2
因为nanoTime使用64位长整型,只有在您连续调用超过292年时才会发生溢出(http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#nanoTime())。 - Gerard
2
@MichaelClerx 我猜你的意思是在0.999999和1.000001之间。 - annedroiid

13

TimeUnit#toMillis(long) (since Java 5)

的意思是将给定的时间段转换为毫秒数,这个方法从Java 5开始可用。
TimeUnit.NANOSECONDS.toMillis(end - start);

或者

Duration#toMillis()(自Java 8以来)

Duration.ofNanos(end - start).toMillis()

OR

Duration#between(Temporal, Temporal) (自 Java 8 开始)

Instant start = Instant.now();
...
Instant end = Instant.now();

Duration.between(start, end).toMillis()

或者

ChronoUnit.html#between(Temporal, Temporal)(自Java 8以来)

Instant start = Instant.now();
...
Instant end = Instant.now();

ChronoUnit.MILLIS.between(start, end)

12

另外需要注意的是,你可以使用TimeUnit类来帮助进行单位转换。在旧版本的Java中,以下代码可能是将处理时间转换为其他时间格式的示例:

long startTime = System.nanoTime();

//Processing in-between.

long endTime = System.nanoTime();
long duration = endTime - startTime;
duration = TimeUnit.SECONDS.convert(duration, TimeUnit.NANOSECONDS);

请注意,较新版本的Java在TimeUnit类中提供了快捷方式。

上述示例将把纳秒转换为秒。还要注意,这会截断一些精度。因此,如果您切换到分钟,则会丢失秒的精度。如果您想获得“12分钟32秒”的结果,则需要对此解决方案进行进一步处理。


2

1

为了获得有意义的结果:

void procedure ( ... )
{
     ...
}

double measureProcedure ( double epsilon , ... )
{
    double mean ;
    double stderr = 2 * epsilon ;
    while ( stderr > epsilon )
    {
         long start = System.nanoTime();
         procedure ( ... ) ;
         long end = System.nanoTime();
         // recalculate mean , stderr 
    }
    return ( mean / 1000000 ) ;
}

1
你可以直接使用System.currentTimeMillis()
注意:

请注意,虽然返回值的时间单位是毫秒,但其粒度取决于底层操作系统,并且可能更大。例如,许多操作系统以十毫秒为单位测量时间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接