system.nanotime()天然免疫时间回拨,因其基于硬件单调计数器(如tsc、clock_monotonic),起点为jvm启动时的任意时刻,只计算流逝时间;用于超时控制时依赖“起点锚定+差值判断”,而非绝对时间比对。

System.nanoTime() 本身不“解决”时间回溯问题,而是天然免疫——它从设计上就绕开了系统墙钟(wall-clock)的干扰,因此不受时间回拨、NTP跳变、手动调时等影响。
为什么它不怕时间回拨?
因为 nanoTime 不读取系统时间,也不依赖任何日历或时钟服务。它的起点是 JVM 启动时选定的一个任意时刻(比如某个 TSC 计数器值),之后全程只靠硬件计数器单调递增。哪怕你把系统时间往前拨 1 小时,nanoTime 返回的数字依然稳定增长,差值永远为正。
- currentTimeMillis() 是“挂钟”:跟着操作系统走,改系统时间就跳变
- nanoTime() 是“跑表”:只记录流逝,不关心现在几点
- 底层通常使用 CLOCK_MONOTONIC(Linux)或 QueryPerformanceCounter(Windows),这些内核时钟明确禁止倒退
它怎么用于超时控制?
关键在于“锚定起点 + 差值判断”,而不是比对绝对时间点。例如设置 500ms 超时:
- 先记下 long start = System.nanoTime()
- 后续循环中持续计算 System.nanoTime() - start
- 只要差值
整个逻辑完全脱离系统时间,即使中间发生 NTP 校正或人为调时,也不会导致提前触发或永久阻塞。
注意:它不是万能的
nanoTime 的“免疫”仅限于单 JVM 进程内的相对耗时测量。它不能:
- 跨 JVM 比较时间戳(起点不同)
- 生成日志时间戳(无日期/时区信息)
- 替代定时调度(如 ScheduledExecutorService 仍需 wall-clock)
- 消除线程调度延迟或 GC 暂停带来的测量污染
真正起作用的是单调性,不是纳秒精度
很多人误以为“纳秒”是核心优势,其实真正关键的是“单调递增”这一特性。哪怕实际分辨率只有 100 纳秒,只要不跳变、不回退,就能可靠支撑超时、限流、性能分析等场景。相比之下,毫秒级但可能突变的 currentTimeMillis(),在高可靠性要求下反而更危险。











