System.nanoTime() 返回纳秒值,需除以1000转换为微秒,但实际分辨率通常为10–100纳秒,无法保证1微秒级精度;推荐整数除法向下取整,避免浮点运算,并注意JIT优化与测量噪声。

Java 中 System.nanoTime() 本身返回的是纳秒(nanosecond)精度的值,但它并不直接提供微秒级计时的 API,而是通过数值换算实现微秒级时间测量——本质是“用纳秒值除以 1000 得到微秒”,但需注意精度、误差和使用边界。
理解 nanoTime 的真实精度与分辨率
System.nanoTime() 返回自某个未指定起始点的纳秒值,其差值可用于计算经过时间。但它不等于硬件纳秒级精度:实际分辨率取决于操作系统和底层时钟(如 HPET、TSC),常见为 10–100 纳秒。这意味着连续两次调用可能返回相同值,或最小可测间隔远大于 1 微秒。
- 在 Linux 上,多数 JVM 使用
CLOCK_MONOTONIC,典型分辨率为 10–50 ns; - Windows 上依赖
QueryPerformanceCounter,通常优于 1 μs; - 不要假设每次调用都能区分 1 μs 差异,尤其在低负载或虚拟机环境中。
安全地转换为微秒单位
若需以微秒为单位表达耗时,直接对纳秒差值做整数除法即可,但要注意舍入方式:
- 向下取整(推荐):
(endNanos - startNanos) / 1000—— 避免浮点运算开销,且语义清晰(不足 1 μs 计为 0); - 四舍五入:
Math.round((double)(endNanos - startNanos) / 1000.0)—— 仅在需要更贴近人类直觉时使用,但引入浮点误差风险; - 避免
/ 1e3或/ 1000.0,防止隐式装箱与 double 运算拖慢高频场景。
高频计时的典型陷阱
在循环内频繁调用 nanoTime() 测量单次操作(如方法调用、加法运算),极易受 JVM 优化干扰:
立即学习“Java免费学习笔记(深入)”;
- JIT 可能内联、消除空操作,导致测出 0 ns;
- 单次测量噪声大(上下文切换、缓存未命中等),应多次采样取统计值(如 warmup + 重复执行 10000 次,排除极值后取中位数);
- 不要用
nanoTime()替代System.currentTimeMillis()做业务时间戳——它不保证与时钟同步,也不反映真实挂钟时间。
一个轻量实用的微秒计时工具片段
无需第三方库,可用如下简洁封装支持可读性与复用:
public class MicroTimer {
private long start;
<pre class='brush:java;toolbar:false;'>public void start() {
start = System.nanoTime();
}
public long elapsedMicros() {
return (System.nanoTime() - start) / 1000;
}} // 使用示例: // MicroTimer timer = new MicroTimer(); // timer.start(); // doWork(); // System.out.println("耗时:" + timer.elapsedMicros() + " μs");


















