system.nanotime() 专用于高精度耗时测量,分辨率通常达微秒级且单调递增;system.currenttimemillis() 用于获取系统时间戳,精度为毫秒但可能跳变或回退。

System.nanoTime() 和 System.currentTimeMillis() 的精度差异,本质不是“谁更准”,而是“准什么”——前者专为测耗时而生,后者专为表时间而设。
精度单位不同,但实际分辨率受限于系统
System.nanoTime() 声称返回纳秒(10⁻⁹秒)值,System.currentTimeMillis() 返回毫秒(10⁻³秒)值。但真实分辨率取决于操作系统和硬件计时器:
- Windows 默认时钟中断周期约 15.6ms,两次 currentTimeMillis() 调用可能返回相同值;nanoTime() 在同一系统上通常可达微秒级(如 1–15μs),远高于毫秒粒度
- Linux 常用 HZ=250(即 4ms 间隔),但 CLOCK_MONOTONIC 支持微秒甚至亚微秒分辨率;nanoTime() 底层多基于它,实际稳定在 1–10 微秒较常见
- macOS 时钟粒度通常为 1ms 左右,nanoTime() 实际表现也优于 currentTimeMillis()
精度背后是设计目的的根本区别
currentTimeMillis() 是“墙上时钟”:它对齐 UTC 时间,可被 NTP 校准、手动修改、闰秒调整——这些都会导致值跳变或回退。它的毫秒值有意义,但差值不可靠。
nanoTime() 是“单调计时器”:从 JVM 启动(或某个硬件事件)起持续递增,不受系统时间干扰。它的纳秒值本身无业务含义,但两次相减得到的差值高度稳定、单调、抗跳变。
- 若系统时间被运维向前拨了 5 分钟,currentTimeMillis() 计算出的耗时可能为负数;nanoTime() 完全不受影响
- GC 暂停、线程调度延迟等会影响两种方法的绝对读数,但 nanoTime() 的差值受其干扰更小,更适合短时测量
不能混用,也不该互转
有人试图用 System.nanoTime() - System.currentTimeMillis() 获取“偏移量”,这是无效操作:
- 起点不同:一个始于 JVM 启动(任意原点),一个始于 1970-01-01(固定纪元)
- 单位与增长机制无关:nanoTime() 是稳定累加的硬件计数器,currentTimeMillis() 是软件同步的系统时间快照
- JVM 不保证二者存在数学关系,JIT 优化或 OS 层行为还可能让结果更难解释
选哪个?看你要解决什么问题
测代码执行耗时、压测响应、算法比对、性能瓶颈定位 → 用 System.nanoTime(),必须成对调用相减
打日志时间戳、设置超时阈值(如 30 秒后断开连接)、生成 Date/Instant、定时调度 → 用 System.currentTimeMillis() 或更推荐的 Instant.now()
- Java 9+ 中 Instant.now() 底层仍调用 currentTimeMillis(),但语义清晰、线程安全、支持 ISO 格式,新项目应优先使用
- 涉及分布式时间比对时,两者都需配合 NTP 或 PTP 校准,且要考虑时钟漂移,不可盲目信任本地值










