测耗时用 nanotime,记日志/超时/时间戳用 currenttimemillis;二者起点、单位、目标不同,严禁混用,如 nanotime 不可用于定时调度或与 currenttimemillis 运算。

选对时间 API,不是靠直觉,而是看它回答什么问题:是“现在几点”,还是“过了多久”。
测耗时,一律用 nanoTime
只要目标是测量代码段执行花了多长时间,System.nanoTime() 就是唯一推荐的选择。
- 它不受系统时钟调整影响——手动改时间、NTP 同步、闰秒都不会导致负值或跳变
- 返回值单调递增,差值恒为正,适合循环内多次采样
- 实际分辨率通常达微秒级(Linux/macOS 常为纳秒,Windows 约 100 纳秒),远高于 currentTimeMillis 的 10–16ms
- 单位是纳秒,计算毫秒需除以 1_000_000.0,不要误除 1000
记日志、做超时、存时间戳,用 currentTimeMillis
当你需要和人类时间对齐、写进数据库、生成订单号、判断是否过期,就该用 System.currentTimeMillis()。
- 它对应 Unix 时间戳,可直接转成 Date、LocalDateTime、ISO 格式,便于展示与归档
- 适合粗粒度超时控制,比如“5 秒内未响应则断开连接”——精度够用,语义清晰
- 注意:不能用于高频短耗时测量,两次调用可能返回相同值,结果为 0
- 若业务强依赖时钟稳定性(如金融撮合),需配合 NTP 监控或硬件时钟校准
绝对不能混用的三种情况
两者起点不同、单位不同、设计目标不同,交叉使用会引入隐蔽错误。
- 不用 nanoTime() 做定时调度(如“10 秒后发通知”),它不映射到真实时间点
- 不拿 currentTimeMillis() 减 nanoTime(),数值无数学关系,结果毫无意义
- 不把 nanoTime() 值传给 Thread.sleep()、ScheduledExecutorService 或任何接受绝对时间的 API
性能敏感场景下的补充建议
在 Windows 环境中,currentTimeMillis() 调用开销略低于 nanoTime(),但精度缺陷往往让这点优势失去价值。
- 避免在每轮 for 循环里反复调用 nanoTime()——计时本身会干扰热点路径,应改用 warmup + 批量采样
- 如需高频低开销时间戳(如日志打点),可考虑封装 CachedClock(定期刷新 currentTimeMillis(),容忍最多几十毫秒误差)
- 真正要压测微基准性能,请用 JMH,它自动处理预热、GC 干扰、JIT 优化等变量











