不推荐用于高精度场景。它返回自1970-01-01 00:00:00 utc起的毫秒数,受ntp校时、手动改时间影响,分辨率仅10–16ms,非单调,易回退跳变,无法满足微秒级精度需求。

用 System.currentTimeMillis() 测量业务代码耗时,**不推荐用于高精度场景**。它返回的是自 1970-01-01 00:00:00 UTC 起的毫秒数,受系统时钟调整(如 NTP 同步、手动修改时间)影响,分辨率通常为 10–16 毫秒(取决于操作系统),无法满足微秒或亚毫秒级精度需求。
为什么 currentTimeMillis 不适合高精度计时
它本质是“墙上时钟”(wall-clock time),不是单调递增的稳定时钟:
- 系统时间被人为或自动校正时(例如 NTP 调整几毫秒),
currentTimeMillis()可能回退或跳变,导致测出负耗时或严重偏差; - 在 Windows 上默认分辨率约 15.2 ms(依赖多媒体定时器),Linux 通常为 1–10 ms,但依然远低于纳秒级要求;
- 两次调用之间可能被 GC、线程调度、CPU 抢占等干扰,误差不可控,尤其在短耗时(
真正适合高精度耗时测量的方法
Java 提供了更可靠的替代方案:System.nanoTime() —— 它基于底层高精度计时器(如 TSC),返回纳秒级单调时间戳,不受系统时钟变更影响,专为性能测量设计:
- 调用开销极小(通常几十纳秒),远低于
currentTimeMillis(); - 结果是相对值,只用于计算差值,不能转成日期或用于超时控制;
- 示例:
long start = System.nanoTime(); // 执行业务逻辑 doSomething(); long end = System.nanoTime(); long durationNs = end - start; // 纳秒级耗时 long durationMs = TimeUnit.NANOSECONDS.toMillis(durationNs); // 转毫秒(四舍五入)
实际使用中的关键细节
即使用了 nanoTime(),也要注意几个易错点:
- 避免直接打印或存储 nanoTime 值:它无业务意义,仅作差值;
- 不要跨 JVM 实例比较 nanoTime:不同 JVM 的起始偏移不同,不可比;
- 短耗时建议多次采样取最小值或中位数:单次测量易受噪声干扰(如上下文切换);
-
生产环境慎用高频打点:频繁调用
nanoTime()本身有开销,大量日志/监控上报反而影响性能。
什么情况下可以勉强用 currentTimeMillis
仅适用于粗粒度、容忍误差的场景:
- 记录接口整体响应时间(> 100ms),且不依赖绝对精度;
- 配合日志打点做大致时段对齐(如“请求在 XX 秒内完成”);
- 老系统受限于 JDK 版本(











