Java中有秒表吗?

145

Java中有计时器吗?
在谷歌上,我只找到了不起作用的计时器代码 - 它们总是返回0毫秒。

我找到的这段代码不起作用,而且我不知道为什么。

public class StopWatch {
  
  private long startTime = 0;
  private long stopTime = 0;
  private boolean running = false;
  
  
  public void start() {
    this.startTime = System.currentTimeMillis();
    this.running = true;
  }
  
  
  public void stop() {
    this.stopTime = System.currentTimeMillis();
    this.running = false;
  }
  
  
  //elaspsed time in milliseconds
  public long getElapsedTime() {
    long elapsed;
    if (running) {
      elapsed = (System.currentTimeMillis() - startTime);
    } else {
      elapsed = (stopTime - startTime);
    }
    return elapsed;
  }
  
  
  //elaspsed time in seconds
  public long getElapsedTimeSecs() {
    long elapsed;
    if (running) {
      elapsed = ((System.currentTimeMillis() - startTime) / 1000);
    } else {
      elapsed = ((stopTime - startTime) / 1000);
    }
    return elapsed;
  }
}

10
你如何确定它没有起作用?(也许你正在测量某些执行时间比System.currentTimeMillis()的精度更高的东西) - nos
5
请发布测试这个类的代码... - DXTR66
3
只想指出,这是《Java编程入门,综合版(第9版)》中的教科书问题之一。 - Sam
5
请勿在生产环境中使用currentTimeMillis(),因为它与系统日期/时间相关,并且不能保证单调递增(例如,您可能会获得负的经过时间)。用于测量时间请使用nanoTime()-它保证单调递增并且专门用于测量目的。请参见https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#nanoTime-- - Nikita Bosik
18个回答

108

101

使用Guava的Stopwatch

一个用于测量经过的时间(以纳秒为单位)的对象。使用此类来测量经过的时间要比直接调用System.nanoTime()有几个好处:

  • 可以替换备用时间源,用于测试或性能方面的原因。
  • 根据nanoTime文档,返回的值没有绝对意义,只能相对于另一个由不同时间返回的nanoTime时间戳进行解释。 Stopwatch是更有效的抽象,因为它仅公开这些相对值,而不是绝对值。
Stopwatch stopwatch = Stopwatch.createStarted();
doSomething();
stopwatch.stop(); // optional

long millis = stopwatch.elapsed(TimeUnit.MILLISECONDS);

log.info("that took: " + stopwatch); // formatted string like "12.3 ms"

4
番石榴的秒表程序缺少“getStartTime()”方法,Apache则缺少“isRunning()”方法。啊! - To Kra
3
@ToKra,您对于开始时间有什么打算呢?由于这是纳秒级别的时间,根据文档所述,您无法对其进行任何有意义的操作。 - Hakanai
1
现在你可以使用这个来获取毫秒数:long stopWatch = stopWatch.elapsed(TimeUnit.MILLISECONDS); - PHPGuru
这是哪个guava版本?我使用了1.8,但它没有找到Stopwatch类。 - Laser Infinite

87

现在你可以尝试类似这样的东西:

Instant starts = Instant.now();
Thread.sleep(10);
Instant ends = Instant.now();
System.out.println(Duration.between(starts, ends));

输出结果遵循ISO 8601标准。


1
快速简便,非常感谢!帮助跟踪任务从开始到结束的持续时间。 - ndm13
如果在睡眠期间更改系统时间会发生什么? - Peteter
1
@Peteter 这只是一个例子。如果你在 Linux 系统上,你必须处理硬件时钟和内核管理的时钟。如果你改变了硬件时钟,那么不会有任何影响,但是在内核管理的时钟中,你将会遇到麻烦:Instant.now() 获取系统时间并显示错误的时间间隔。 - Valtoni Boaventura
不要忘记 java.time.Instant 是不可变的和线程安全的 :) - Amos Kosgei
2
使用Java 8的导入,这只是一个示例,David。在进入生产之前,请进行适当调整。 - Valtoni Boaventura
显示剩余2条评论

58

Spring提供了一个优雅的org.springframework.util.StopWatch类(spring-core模块)。

StopWatch stopWatch = new StopWatch();

stopWatch.start();
// Do something
stopWatch.stop();

System.out.println(stopWatch.getTotalTimeMillis());

9

虽然没有内置的秒表工具,但自从JSR-310(Java 8 Time)推出后,你可以轻松实现这一功能。

ZonedDateTime now = ZonedDateTime.now();
// Do stuff
long seconds = now.until(ZonedDateTime.now(), ChronoUnit.SECONDS);

我没有进行过充分的基准测试,但我猜想使用Guava的Stopwatch会更加有效。


8

代码无法运行,因为getElapsedTimeSecs()中的elapsed变量不是floatdouble类型。


6

使用System.currentTimeMillis()来获取开始时间和结束时间,并计算其差值。

class TimeTest1 {
  public static void main(String[] args) {

    long startTime = System.currentTimeMillis();

    long total = 0;
    for (int i = 0; i < 10000000; i++) {
      total += i;
    }

    long stopTime = System.currentTimeMillis();
    long elapsedTime = stopTime - startTime;
    System.out.println(elapsedTime);
  }
} 

点击此教程了解更多信息


1
如其他地方所述,currentTimeMillis()与系统日期/时间相关,并不能保证单调性(例如,您可能会得到负的经过时间)。 - oligofren
不要使用System.currentTimeMillis()来测量经过的时间。 - Valdemar

3
使用:com.google.common.base.Stopwatch,它简单易用。
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>

例子:

Stopwatch stopwatch = new Stopwatch();
stopwatch.start();

"Do something"

logger.debug("this task took " + stopwatch.stop().elapsedTime(TimeUnit.MILLISECONDS) + " mills");

这个任务花费了112毫秒


3

试试这个:

/*
 * calculates elapsed time in the form hrs:mins:secs
 */
public class StopWatch
{ 
    private Date startTime;

    public void startTiming()
    {
        startTime = new Date();
    }

    public String stopTiming()
    {
        Date stopTime = new Date();
        long timediff = (stopTime.getTime() - startTime.getTime())/1000L;
        return(DateUtils.formatElapsedTime(timediff));
    }

}

使用:

StopWatch sw = new StopWatch();
...
sw.startTiming();
...
String interval = sw.stopTiming();

2
DateUtils是Apache Commons的一部分,为什么不直接使用它们的StopWatch? - Bill Effin Murray
在大多数情况下,你会使用一些常见的库,就像其他答案中提到的(例如Apache Commons)。如果不需要全部功能,甚至可以只选择库的部分内容。 - Guy

2

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