首选 System.nanoTime() 测量算法执行时间,因其基于单调计数器、精度达纳秒级、不受系统时间跳变影响,适合微基准测试;currentTimeMillis() 仅适用于粗略超时或状态检查等低精度场景。

测量算法执行时间,首选 System.nanoTime(),而不是 System.currentTimeMillis()。它专为耗时测量而生,不受系统时间跳变影响,精度达纳秒级,能真实反映代码段的运行开销。
为什么 nanoTime() 更适合算法效率对比
算法性能测试关注的是“这段代码实际花了多少时间”,而非“它在几点几分几秒执行”。nanoTime() 提供单调、高分辨率的时间源,天然契合这一目标:
- 返回值基于 JVM 启动后的稳定计数器,不会因 NTP 同步或管理员调时而倒退或突变
- 典型分辨率在 100 纳秒以内(Linux/macOS 可达 1 纳秒),远高于
currentTimeMillis()在 Windows 上常见的 15 毫秒粒度 - 即使两次调用间隔仅几十纳秒,也能区分出差异,这对排序、查找、哈希等轻量操作的微基准测试至关重要
正确写法:避免常见误用
直接用纳秒差值是基础,但要注意细节才能让对比结果可信:
- 每次测试前应预热 JVM(如先运行几次目标方法),避免 JIT 编译过程干扰首轮耗时
- 单次测量易受 GC、线程调度等噪声影响,建议循环多次取中位数或平均值
- 不要混用单位:用
nanoTime()开始和结束,差值仍是纳秒;转毫秒时用/ 1_000_000,不是除以 1000 - 避免在测量块内做 I/O、打印、对象创建等非目标操作,否则测的不是算法本身
一个实用的对比示例
比如比较冒泡排序与 Arrays.sort() 的性能:
立即学习“Java免费学习笔记(深入)”;
long start = System.nanoTime();
bubbleSort(arr.clone()); // 避免原数组被修改影响后续测试
long bubbleNs = System.nanoTime() - start;
<p>start = System.nanoTime();
Arrays.sort(arr.clone());
long quickNs = System.nanoTime() - start;</p><p>System.out.printf("Bubble: %.3f ms, Quick: %.3f ms%n",
bubbleNs / 1_000_000.0,
quickNs / 1_000_000.0);
注意使用 .clone() 保证输入一致,用 double 除法保留小数,输出更直观。
什么时候可以考虑 currentTimeMillis()
若你只是粗略验证某段逻辑“大概没卡死”,比如后台任务每 5 秒检查一次状态,用 currentTimeMillis() 完全够用。但它不适合:
- 执行时间短于 10 毫秒的算法
- 需要跨机器比对耗时的分布式压测
- 对时间敏感的超时控制(如限流、熔断)



















