system.nanotime() 是专为高精度时间测量设计的单调递增纳秒计时器,分辨率10–100纳秒,不受系统时间跳变影响,适用于性能分析、帧同步等场景,但需配合预热、多轮采样、异常剔除等工程化方法使用。

System.nanoTime() 是 Java 中专为高精度时间测量设计的 API,它不提供“当前时间”,而是返回一个单调递增的纳秒级计时值,适用于测间隔、做性能分析、实现帧同步等场景。相比 System.currentTimeMillis(),它在精度、稳定性与适用性上具有不可替代的优势。
纳秒级分辨率,远超系统时钟粒度
Windows 默认时钟中断周期约 15.6 毫秒,Linux 通常为 1–4 毫秒,macOS 接近 1 毫秒——这些都远低于游戏逻辑(如 16ms/帧)或算法微基准(常需微秒级)的要求。而 System.nanoTime() 在主流平台实际分辨率可达 10–100 纳秒,足够分辨毫秒内多次执行的差异。
- 它底层调用操作系统单调时钟(如 Linux 的 CLOCK_MONOTONIC),不受系统时间跳变影响
- 两次调用差值(end - start)是稳定、可比、无回跳的,这是性能对比的核心前提
- 即使硬件无法真正达到纳秒物理精度,其差值在单次 JVM 运行中仍具备高度一致性
完全规避系统时间干扰
System.currentTimeMillis() 返回的是挂钟时间,直接受 NTP 同步、手动修改、闰秒等影响。一次系统时间回拨会导致耗时计算为负;向前跳跃则造成“时间压缩”,严重扭曲统计结果。
- nanoTime() 基于 JVM 启动时刻的任意起点,只保证单调递增,天生免疫时钟漂移
- 日志打点若需“带时间戳的耗时”,应分开记录:currentTimeMillis() 用于对齐时间线,nanoTime() 用于计算精确差值
- 绝不能将 nanoTime() 与 currentTimeMillis() 混合运算——单位错乱、语义失效、结果无意义
专为性能测量而生,但用法有讲究
它不是“万能秒表”,直接测单次空操作常得 0,是因为调用开销、JIT 优化或底层分辨率限制。真正可靠的测量必须配合工程化方法:
- 先预热:让目标代码被 JIT 编译、类完成初始化,避免把编译开销计入结果
- 多轮采样:每轮执行数百至数万次,再用总耗时除以次数,大幅降低计时器开销占比
- 剔除异常:取多轮均值的中位数,比算术平均更能抵抗 GC、中断等毛刺干扰
- 隔离干扰:避免在测量段内包含 I/O、锁等待、网络调用等非 CPU 计算行为
单位转换要保留精度,避免截断失真
纳秒值本身是 long 类型整数,转成毫秒时若简单除以 1_000_000,会直接截断小数部分。例如 1,234,567ns → 1ms,丢失近 23% 的信息。
- 性能监控建议保留原始纳秒值入库,展示时再统一转为微秒(/1000)或毫秒(/1_000_000.0)
- 需四舍五入可用 Math.round(durationNs / 1_000_000.0),更符合人类感知
- 关键指标(如 P95/P99 延迟)务必基于纳秒原始数据计算,避免多次除法引入累积误差
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











