【问题标题】:Joda-Time getMillisOfDay() seems to be advancing more rapidly than java.util.Date's getTime() milliseconds valueJoda-Time getMillisOfDay() 似乎比 java.util.Date 的 getTime() 毫秒值进展得更快
【发布时间】:2014-04-05 04:51:02
【问题描述】:

我刚开始使用Joda-Time,遇到了一些看起来很奇怪的东西。

当我睡眠 1 毫秒并在睡眠前后调用 getMillisOfDay() 时,Joda-Time 告诉我已经过去了 119 毫秒。使用 java.util.Date (在睡眠前后创建一个实例,并获取每个返回的 getTime() 值的差异)报告的经过时间值要小得多(2 毫秒)。这比 1 毫秒的实际睡眠时间长,但我猜测创建 Date 的对象开销会产生影响,无论如何报告 java.util.Date 的经过时间远低于 Joda-Time 报告的时间.)

这是我的小测试方法:

@Test(enabled = true)
public void testsleep() {

    LocalDateTime now = new  LocalDateTime();
    System.out.println("jodatime before millisecs:" + now.getMillisOfDay());
    Thread.sleep(1);
    LocalDateTime now2 = new  LocalDateTime();
    System.out.println("jodatime  after millisecs:" + now2.getMillisOfDay());

    System.out.println("java.util.DATE before call:" + new Date().getTime());
    Thread.sleep(1);
    Date after = new Date();
    System.out.println("java.util.DATE after call:" + after.getTime());

    println "done"
}

输出:

jodatime before millisecs:76672505
jodatime  after millisecs:76672624
java.util.DATE before call:1396671472633
java.util.DATE after call:1396671472635

分析:

jodatime  after millisecs:76672624
jodatime before millisecs:76672505
                        ----------------
                    119 millisecs elapsed according to joda time

java.util.DATE  after call:1396671472635
java.util.DATE before call:1396671472633
                        ----------------
                    2 millisecs elapsed according to java util Date

我认为 Joda-Time 比 java.util.Date 更好。好吧,我敢肯定,我只是用错了。但我不明白怎么做。非常感谢任何建议!

【问题讨论】:

  • 没有像 LocalDateTime 这样的类是 Joda-Time。你的意思是DateTime 还是LocalTime?请说明,因为您提出了一个奇怪的问题。
  • 谢谢安东尼。我站得更正了。 LocalDateTimeis an unmodifiable datetime class representing a datetime without a time zone.
  • 不足为奇:new Date()new LocalDateTime() 轻得多,因此存在差异。但是,Anthonys 的替代方案确实更适合进行基准测试。
  • 仅供参考,看看Java Microbenchmark Harness (JMH) 工具。 JEP 230 建议将此添加到 OpenJDK。

标签: java jodatime


【解决方案1】:

我既不会使用Date 也不会使用LocalDateTime 来测量短时间间隔。写在您的问题中的主要原因是创建对象的开销很大(请查看LocalDateTime source code)。另请记住,JVM 需要一些时间来预热(让 JVM 优化发挥作用)。

虽然您不应该这样进行基准测试(有很多好的 Java 基准测试工具),但一个好的低级替代方案是 System.nanoTime()StopWatch 类也可能派上用场(如 GuavaCommons LangSpring 实现)。

最后,请记住Thread.sleep 本身就存在精度问题。

// Run several times to *warm up*
for (int i = 0; i < 100; i++) {
    double init = System.nanoTime();
    Thread.sleep(1);
    long end = System.nanoTime();
    System.out.printf("Elapsed time: %.2f milliseconds\n", (end - init) * 1e-6); 
}

【讨论】:

  • 好的,我买那个。似乎 Joda 时间的人应该更新他们的文档以警告这些类不应该用于毫秒级精度操作。我看了看源代码.. 没有看到任何看起来非常耗费资源的东西,这将有助于 100 毫秒的处理时间。我很想知道你认为的罪魁祸首是什么……但这只是好奇……我现在知道不要依赖 Joda 时间来进行低分辨率跟踪。但实际上 java.util.Date 似乎确实给了我准确的结果。哦,好吧.. 让我们希望 java 1.8 能解决这一切!谢谢! /cb
  • 其实我不同意,问题不在于 Joda-Time 精度,而是您使用错误工具(部分)进行工作(测量持续时间)的方式。 Instant.now().getMillis() 将更好地为账单服务。此外,您的基准测试存在缺陷,即使使用损坏的 LocalDateTime.getMillisOfDay() 方法,预热后也没有 100 毫秒的处理时间。
  • 关于 JSR 310(日期和时间)与 Joda-Time,我写过 my own flawed benchmark 并使用 Java 8 运行它。每种测量方法都非常精确,平均接近 1 毫秒的预期结果。即使是损坏的getMillisOfDay() 方法在最初的预热之后也没有问题,平均略高于 1 毫秒(第一次运行花费了近 30 毫秒;根据 Netbeans Profiler,昂贵的部分与ISOChronology.getInstance 有关)。结论:对微观基准非常非常小心。
  • Java 9 brings a new implementation of Clock 能够以高达纳秒的分辨率捕获当前时刻。可能有助于基准测试(我不知道;尚未尝试或查看详细信息)。
猜你喜欢
  • 2017-03-05
  • 2011-05-23
  • 2017-07-10
  • 1970-01-01
  • 2013-08-18
  • 1970-01-01
  • 2015-10-08
  • 2017-03-06
  • 2012-08-15
相关资源
最近更新 更多