不推荐用于精确性能测量。System.currentTimeMillis() 受 NTP 校时、系统休眠、时钟回拨影响,分辨率仅 10–16ms,测短耗时不准;应优先用 System.nanoTime() 测间隔,或使用 JMH 等专业工具。

用 System.currentTimeMillis() 测量耗时是否靠谱
不推荐用于精确性能测量。它返回的是自 1970-01-01 00:00:00 UTC 起的毫秒数,底层依赖系统时钟,受系统时间调整(如 NTP 同步、手动改时间)、时钟漂移影响,分辨率通常只有 10–16ms(Windows 常见),在短于 10ms 的代码段上基本测不准。
System.currentTimeMillis() 和 System.nanoTime() 怎么选
测「经过时间」(elapsed time)——比如接口响应、文件读写、循环执行耗时——该用 System.nanoTime();System.currentTimeMillis() 只适合记录「业务时间戳」(如日志打点、超时截止时间计算)。
-
System.nanoTime()基于高精度计时器(如 TSC 寄存器),不受系统时间修改影响,纳秒级分辨率(实际精度取决于硬件和 OS,但至少是微秒级) -
System.currentTimeMillis()返回值可能倒退(NTP 回拨)、跳跃(时区切换、夏令时),导致end - start出负数 - 两者单位不同:
currentTimeMillis()是毫秒,nanoTime()是纳秒,别混用或直接除 1_000_000 错误换算
写法上最容易错的三个地方
即使坚持用 System.currentTimeMillis(),也常因细节翻车:
- 把
start和end都放在 try 块里,但异常抛出后end没执行,导致后续end - start用到未初始化变量 - 忽略 JVM 预热和 JIT 编译干扰:首次运行慢、多次运行后变快,单次测量毫无意义
- 在循环外只调一次
currentTimeMillis(),误以为能代表“平均耗时”,其实只是总耗时;要测平均,得在循环内分别打点(或改用nanoTime+ 累加)
正确姿势示例(仅限粗略观察):
long start = System.currentTimeMillis();
doSomething();
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start) + " ms");
真要压测或定位性能瓶颈怎么办
别自己手写计时逻辑。JMH(Java Microbenchmark Harness)是标准方案,它自动处理预热、GC 干扰、统计显著性;如果只是临时调试,至少用 System.nanoTime() 替代:
long start = System.nanoTime();
doSomething();
long end = System.nanoTime();
System.out.println("耗时:" + (end - start) / 1_000_000.0 + " ms");
注意:nanoTime() 的绝对值无意义,只看差值;它的值可能溢出(但要连续运行数百年才溢),不用做额外防护。
真正难的不是记两个时间戳,而是确保你测的确实是目标代码,而不是 GC、线程调度、CPU 频率波动或者 JIT 插入的隐藏开销。










