【发布时间】:2010-09-19 07:55:00
【问题描述】:
什么是使用 Java 访问系统时钟的简单/简便方法,以便我可以计算事件的经过时间?
【问题讨论】:
什么是使用 Java 访问系统时钟的简单/简便方法,以便我可以计算事件的经过时间?
【问题讨论】:
我会避免使用System.currentTimeMillis() 来测量经过的时间。 currentTimeMillis() 返回“挂钟”时间,该时间可能会发生变化(例如:夏令时、管理员用户更改时钟)并扭曲您的间隔测量。
另一方面,System.nanoTime() 返回自“某个参考点”(例如,JVM 启动)以来的纳秒数,因此不会受到系统时钟变化的影响。
【讨论】:
这是一些示例代码。
long startTime = System.currentTimeMillis();
// Run some code;
long stopTime = System.currentTimeMillis();
System.out.println("Elapsed time was " + (stopTime - startTime) + " miliseconds.");
【讨论】:
Apache Commons-Lang 也有适合您的目的的 StopWatch 类。它使用 System.currentTimeMillis(),所以你仍然会遇到分辨率问题,但你可以暂停并做单圈时间等。我现在将它用作事件统计的标准。
http://commons.apache.org/lang/api-release/org/apache/commons/lang/time/StopWatch.html
Answer by Leigh 是正确的。
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 中,获取当前时刻仅解析为毫秒分辨率(最多 3 位小数秒的小数部分)。因此,虽然 java.time 类可以存储纳秒,但它们只能以毫秒确定当前时刻。此限制是由于遗留问题造成的(默认的Clock 实现使用System.currentTimeMillis())。
在 Java 9 及更高版本中,默认的 Clock 实现可以以纳秒的分辨率确定当前时刻。实际上,这样做取决于您计算机时钟硬件的精细程度。
有关更多信息,请参阅此 OpenJDK 问题页面:Increase the precision of the implementation of java.time.Clock.systemUTC()
如果您的目的是进行基准测试,请务必查看其他问题,例如:
框架可用于协助进行短期基准测试。
【讨论】:
java.lang.System.currentTimeMillis() 或 java.lang.System.nanoTime() 应该可以测量经过的时间。
【讨论】:
这是我使用 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;
}
【讨论】: