1. 前提概要
- System.currentTimeMillis()是系统时间,系统时间修改、闰秒会导致跳动。
- System.nanoTime()仅用于计算耗时,和系统时间没有强关联。
- System.nanoTime()单位是纳秒,但不保证有纳秒的精度,但保证精度至少比System.currentTimeMillis()高。
- UTC时间实际一天可能是86399或86401秒,标准时间是有铯133衰变周期决定的,需要对齐太阳日。
- Java时间标准(Time-Scale)把每一天都精确的定义为86400秒,会忽略闰秒。
- Java8开始引入Instant和Duration,使用Java时间标准(Time-Scale)。这两个类是线程安全的。
2. 为什么System.currentTimeMillis()不适合计算执行时间?
因为系统时间修改或者闰秒的问题,currentTimeMillis跳动会导致计算不准确。
3. 可选的方案
3.1 Java8的Instant和Duration
Instant使用Java的时间标准,精确的86400秒,不存在闰秒的问题。
Instant start = Instant.now();
// CODE HERE
Instant finish = Instant.now();
long timeElapsed = Duration.between(start, finish).toMillis();
3.2 使用Apache Comman Lang里的StopWatch
引入依赖
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.7</version>
</dependency>
Java代码
StopWatch watch = new StopWatch();
watch.start();
// CODE HERE
watch.stop();
System.out.println("Time Elapsed: " + watch.getTime());
4. 延伸阅读
JMH(Java Microbenchmark Harness),Java9开始会成为OpenJDK的一部分。JMH会处理JVM热身(warm-up)和代码优化(code-optimization),这样测试的结果会更准一些。