system.currenttimemillis()适用于≥100ms的业务逻辑块性能打点,精度低(1–15ms)、易受时钟漂移和回拨影响,需封装使用、记录起止时间戳并加标签,短操作或分布式场景应换用nanotime或apm工具。

用 System.currentTimeMillis() 做性能打点简单直接,但容易因精度低、时钟漂移或调用开销误判瓶颈。关键不是“能不能用”,而是“怎么用才靠谱”。
明确适用场景:别在毫秒级敏感处硬扛
该方法返回自 1970-01-01 00:00:00 UTC 起的毫秒数,系统底层依赖 OS 时钟,通常精度为 10–15ms(Windows)或 1–10ms(Linux)。这意味着:
- 两次调用间隔若小于 10ms,可能返回相同值,导致“耗时 0ms”假象
- 不适合测量单次短操作(如一次 HashMap.get()),更适合 ≥100ms 的业务逻辑块(如一次 HTTP 请求处理、批量数据导出)
- 跨线程或分布式场景下无法对齐时间基准,不适用于链路追踪
规范打点写法:减少干扰,保留可读性
避免裸写 long start = System.currentTimeMillis(),推荐封装成轻量工具或统一模板:
- 用 try-finally 或 try-with-resources 保证结束时间必采集,防止异常跳过统计
- 记录起止时间戳 + 计算耗时,而非只存差值——便于后续排查时钟回拨或系统时间被修改
- 搭配有意义的标签,例如:
"order-service|createOrder|step1-validate",方便聚合分析
示例片段:
long startTs = System.currentTimeMillis();
try {
doSomething();
} finally {
long endTs = System.currentTimeMillis();
long costMs = endTs - startTs;
log.info("perf|{}|{}|{}", "createOrder", startTs, costMs);
}
识别并规避常见陷阱
看似简单,实操中几个细节常引发误判:
-
不要重复调用:同一方法内多次调用
currentTimeMillis()不会提升精度,反而增加 CPU 开销(虽小但无意义) -
警惕时钟回拨:NTP 同步或手动改系统时间会导致时间戳倒退,出现负耗时;可在日志中同时记录
System.nanoTime()做辅助校验(仅用于同一线程内相对耗时) - 避免日志本身拖慢测量:高频率打点时,异步日志或缓冲写入更安全;否则日志 I/O 可能成为实际瓶颈
进阶替代建议:什么时候该换方案
当需求升级,就该考虑更合适的工具:
- 需要微秒/纳秒级精度 → 用
System.nanoTime()(注意它不表示绝对时间,只适合计算差值) - 要统计多个嵌套阶段或跨线程耗时 → 引入 Micrometer + Prometheus 或 SkyWalking 等 APM 工具
- 做压测或基准测试 → 配合 JMH,屏蔽 JIT、GC、OS 调度等干扰因素
不复杂但容易忽略。用对地方,currentTimeMillis 仍是最快上手的轻量监控起点。











