【问题标题】:How do I calculate the elapsed time of an event in Java? [duplicate]如何在 Java 中计算事件的经过时间? [复制]
【发布时间】:2010-09-19 07:55:00
【问题描述】:

什么是使用 Java 访问系统时钟的简单/简便方法,以便我可以计算事件的经过时间?

【问题讨论】:

    标签: java time timer clock


    【解决方案1】:

    我会避免使用System.currentTimeMillis() 来测量经过的时间。 currentTimeMillis() 返回“挂钟”时间,该时间可能会发生变化(例如:夏令时、管理员用户更改时钟)并扭曲您的间隔测量。

    另一方面,System.nanoTime() 返回自“某个参考点”(例如,JVM 启动)以来的纳秒数,因此不会受到系统时钟变化的影响。

    【讨论】:

    • 很高兴知道。不知道currentTimeMillis()和nanoTime()除了分辨率还有区别。
    • 我认为夏令时不会影响 currentTimeMillis()。它是根据 UTC 定义的。
    • @Shiny:关于 UTC 的好点 - 我没有意识到这一点。我认为我的回应的要点仍然存在,即 currentTimeMillis() 受到挂钟变化的影响。 NTP 更新是 currentTimeMillis() 问题的另一个可能来源。
    • System.nanoTime() 是否也能抵抗 CPU 频率变化?
    • 在我对这个问题的另一个实例的回答中查看更多详细信息,该问题已作为副本关闭:stackoverflow.com/questions/1770010/…
    【解决方案2】:

    这是一些示例代码。

    long startTime = System.currentTimeMillis();
    // Run some code;
    long stopTime = System.currentTimeMillis();
    
    System.out.println("Elapsed time was " + (stopTime - startTime) + " miliseconds.");
    

    【讨论】:

    • 我的编辑评论是“修复方法名称“currentTimeMilis”->“currentTimeMillis”。使代码复制/粘贴。(FWIW)“但找不到更多要编辑的字符:(
    • @Diederik 谢谢。我已经修好了。
    • 如果在“运行一些代码”期间机器是 Windows 10 或更高版本并在 Thread.sleep() 期间进入 S3 睡眠,我认为这不会起作用。见:stackoverflow.com/questions/29394222/…
    【解决方案3】:

    Apache Commons-Lang 也有适合您的目的的 StopWatch 类。它使用 System.currentTimeMillis(),所以你仍然会遇到分辨率问题,但你可以暂停并做单圈时间等。我现在将它用作事件统计的标准。

    http://commons.apache.org/lang/api-release/org/apache/commons/lang/time/StopWatch.html

    【解决方案4】:

    Answer by Leigh 是正确的。

    java.time

    Java 8 及更高版本内置了 java.time 框架。

    Instant 是 UTC 时间线上的一个时刻,分辨率为纳秒(最多 9 位小数秒的小数部分)。 now 方法获取当前日期时间时刻。

    Instant now = Instant.now();
    

    2016-03-12T04:29:39.123Z

    您可以将一对Instant 对象之间的经过时间计算为Duration。持续时间使用纳秒分辨率,最大值为可以长时间保持的秒数。这比目前估计的宇宙年龄要大。

    Duration duration = Duration.between( startInstant , stopInstant );
    

    Duration::toString 的默认输出是标准的ISO 8601 格式。您还可以询问纳秒 (toNanos) 或毫秒 (toMillis) 的总计数,以及其他数量。

    Java 8

    在 Java 8 中,获取当前时刻仅解析为毫秒分辨率(最多 3 位小数秒的小数部分)。因此,虽然 java.time 类可以存储纳秒,但它们只能以毫秒确定当前时刻。此限制是由于遗留问题造成的(默认的Clock 实现使用System.currentTimeMillis())。

    Java 9

    在 Java 9 及更高版本中,默认的 Clock 实现可以以纳秒的分辨率确定当前时刻。实际上,这样做取决于您计算机时钟硬件的精细程度。

    有关更多信息,请参阅此 OpenJDK 问题页面:Increase the precision of the implementation of java.time.Clock.systemUTC()

    微基准

    如果您的目的是进行基准测试,请务必查看其他问题,例如:

    框架可用于协助进行短期基准测试。

    【讨论】:

      【解决方案5】:

      java.lang.System.currentTimeMillis()java.lang.System.nanoTime() 应该可以测量经过的时间。

      【讨论】:

      • 请记住,即使这些函数返回的值分别以毫秒和纳秒为单位,但时钟分辨率可能不会那么高。 15 毫秒的时钟分辨率很常见——在对非常短的事件进行计时时请记住这一点。
      • 我在 Windows 上的 LockSupport.parkNanos() 在分辨率方面有很好的经验 - 但我承认这不是秒表的候选人。
      【解决方案6】:

      这是我使用 System.nanoTime() 编写的一个小型 StopWatch 类,正如 Leigh 的回答中所建议的那样:

      public class StopWatch {
          // Constructor
          public StopWatch() {
          }
      
          // Public API
          public void start() {
              if (!_isRunning) {
                  _startTime = System.nanoTime();
                  _isRunning = true;
              }
          }
      
          public void stop() {
              if (_isRunning) {
                  _elapsedTime += System.nanoTime() - _startTime;
                  _isRunning = false;
              }
          }
      
          public void reset() {
              _elapsedTime = 0;
              if (_isRunning) {
                  _startTime = System.nanoTime();
              }
          }
      
          public boolean isRunning() {
              return _isRunning;
          }
      
          public long getElapsedTimeNanos() {
              if (_isRunning) {
                  return System.nanoTime() - _startTime;
              }
              return _elapsedTime;
          }
      
          public long getElapsedTimeMillis() {
              return getElapsedTimeNanos() / 1000000L;
          }
      
          // Private Members
          private boolean _isRunning = false;
          private long _startTime = 0;
          private long _elapsedTime = 0;
      }
      

      【讨论】:

      • 我建议添加方便的方法来获取秒值和带有布尔标志的构造函数,这将允许秒表立即启动。至少这是我需要的,在我使用了你的课程之后:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-15
      • 1970-01-01
      • 2020-04-23
      • 2010-11-15
      • 2010-12-18
      相关资源
      最近更新 更多