System.nanoTime()是Java中获取高精度单调时间戳的推荐方式,适用于性能测量等场景,仅用于计算时间间隔而非绝对时间,应基于“起始时刻+持续时间”建模,避免转换精度损失和累积误差。

System.nanoTime() 是 Java 中获取高精度、单调递增纳秒时间戳的推荐方式,特别适合实现精确计时器(如性能测量、超时控制、动画帧调度等)。它不受系统时钟调整影响,且分辨率通常优于 System.currentTimeMillis(),但**不表示绝对时间,仅用于计算时间间隔**。
核心设计原则
基于 nanoTime() 的计时器应围绕“起始时刻 + 持续时间”建模,避免依赖绝对时间或重复调用造成累积误差:
- 启动时只调用一次
System.nanoTime()记录基准值(startNanos) - 后续所有耗时判断均通过
current = System.nanoTime(); elapsed = current - startNanos计算 - 不将 nanoTime 值转为毫秒或秒后再参与运算(避免整数截断或浮点精度丢失)
- 注意 long 类型溢出风险:nanoTime 约每 292 年溢出一次,常规计时场景可忽略
基础单次计时器实现
适用于一次性的耗时统计(如方法执行时间):
public class NanoStopwatch {
private final long start;
<pre class='brush:php;toolbar:false;'>public NanoStopwatch() {
this.start = System.nanoTime();
}
public long elapsedNanos() {
return System.nanoTime() - start;
}
public double elapsedMillis() {
return elapsedNanos() / 1_000_000.0;
}
public long elapsedSeconds() {
return elapsedNanos() / 1_000_000_000L;
}} // 使用示例: // NanoStopwatch sw = new NanoStopwatch(); // doWork(); // System.out.println("耗时:" + sw.elapsedMillis() + " ms");
可重置/持续运行的计时器
支持暂停、恢复、重置,适合 UI 动画或任务监控:
- 维护
base(已冻结的累计时间)、start(当前运行段起点)、isRunning状态 -
pause():保存当前已运行时间到base,清空start -
resume():仅重设start = System.nanoTime(),不修改base -
reset():清空base和start,状态归零
超时等待辅助类(推荐封装)
避免在循环中反复调用 nanoTime() 判断超时(低效且易出错),可提供简洁 API:
public class NanoTimeout {
private final long deadline;
<pre class='brush:php;toolbar:false;'>public NanoTimeout(long nanos) {
this.deadline = System.nanoTime() + nanos;
}
public boolean isExpired() {
return System.nanoTime() >= deadline;
}
public long remainingNanos() {
return Math.max(0, deadline - System.nanoTime());
}} // 使用示例: // NanoTimeout timeout = new NanoTimeout(TimeUnit.SECONDS.toNanos(5)); // while (!done && !timeout.isExpired()) { // doStep(); // }

















