System.nanoTime()提供纳秒级高精度单调时间戳,需手动记录起止时间求差;最小耗时需预热、多次测量、剔除异常值后取最小值,以规避JVM预热、GC等干扰,而currentTimeMillis()精度低且受系统时钟调整影响。

System.nanoTime() 本身不直接“计算最小耗时”,而是提供高精度、单调递增的时间戳,你需要用它手动记录起止时间,再做差值;而“最小耗时”需多次运行取最小值,以规避 JVM 预热、GC、系统调度等干扰。
为什么不用 System.currentTimeMillis()?
它精度低(通常毫秒级),且可能受系统时钟调整影响(如 NTP 同步),不适合测微小、精确的执行时间。nanoTime 返回的是纳秒级逻辑时间(基于 CPU 计数器),精度高(通常几十纳秒)、单调、不受系统时钟跳变影响。
基本测量写法(单次)
在函数调用前后各调一次 nanoTime,相减即得本次耗时(单位:纳秒):
long start = System.nanoTime(); myMethod(); long end = System.nanoTime(); long durationNs = end - start;
注意:
- 不要对 durationNs 做除法转毫秒再四舍五入再转回纳秒,会损失精度;
- 如果函数极快(比如几纳秒),单次测量可能被噪声淹没,结果不可靠。
获取“最小耗时”的实用做法
最小耗时 ≠ 一次最快的结果,而是多次运行中排除预热、抖动后最可信的下界。推荐步骤:
立即学习“Java免费学习笔记(深入)”;
- 先预热:循环调用目标方法 1000–10000 次(不计时),让 JIT 编译器完成优化;
- 正式测量:再运行足够多次(如 10000–100000 次),每次记录耗时;
- 剔除异常值:去掉前 1% 和后 1%(或直接去掉最大几个);
- 取剩余值中的最小值 —— 这更接近函数“稳定状态下的最佳性能下限”。
示例关键逻辑(简化版):
// 预热
for (int i = 0; i < 5000; i++) myMethod();
<p>// 测量并收集
long[] times = new long[10000];
for (int i = 0; i < times.length; i++) {
long s = System.nanoTime();
myMethod();
times[i] = System.nanoTime() - s;
}
Arrays.sort(times);
long minStable = times[100]; // 跳过前1%</p>注意事项和常见陷阱
- 避免测量含 I/O、锁、随机数、当前时间等外部依赖的方法——它们天然波动大,“最小值”无意义;
- JIT 优化可能把空循环或无副作用代码完全消除(dead code elimination),记得让返回值参与后续计算(如累加后打印),或用
Blackhole(JMH 中)防止优化; - nanoTime 开销本身约 10–30 纳秒,若函数本身也只几十纳秒,测量误差占比就很高,此时应测批量操作(如处理 1000 个元素)再均摊;
- 真正严谨的微基准测试请用 JMH(Java Microbenchmark Harness),它自动处理预热、Fork、统计校准、防止优化等问题。


















