System.nanoTime() 返回纳秒值,直接除以1000得整数微秒会截断余数导致精度丢失;需根据场景选整数截断、四舍五入或浮点运算,并注意除法类型与硬件分辨率限制。

为什么 System.nanoTime() 返回值不能直接当微秒用
因为 System.nanoTime() 返回的是纳秒(ns)单位的整数,而“微秒”是 1000 纳秒。直接除以 1000 得到的仍是整数,但会截断余数,比如 1234ns ÷ 1000 = 1μs,丢失了 234 纳秒的细节;若需保留小数位表达更真实的时间粒度,必须转为浮点运算。
微秒级耗时计算的三种常见写法及适用场景
假设你已用 System.nanoTime() 获取了起止时间差 durationNs:
-
整数微秒(截断):
long microseconds = durationNs / 1000;—— 适合日志打点、简单阈值判断(如 “是否超过 100μs”),但会系统性低估真实耗时 -
带一位小数的微秒(四舍五入):
long microseconds = Math.round(durationNs / 1000.0);—— 更符合人类对“约多少微秒”的感知,避免因截断导致的统计偏差 -
浮点微秒(保留精度):
double microseconds = durationNs / 1000.0;—— 用于性能分析工具、绘图或后续做平均/分位数计算,不丢失任何原始信息
容易被忽略的精度陷阱:除以 1000 还是 1000.0?
Java 中整数除法会自动向下取整,durationNs / 1000 是 long ÷ int → long,结果永远丢小数;而 durationNs / 1000.0 是 long ÷ double → double,才能保留小数部分。实际调试中,看到 1999ns 输出为 1μs 却以为代码只跑了 1 微秒,其实是除法类型没选对。
另外注意:JVM 不保证 System.nanoTime() 的底层分辨率真能达到 1 纳秒——Linux 下常为 ~10–15 纳秒,Windows 下可能更高。所以“显示 1234.5μs”不等于物理上精确到 0.1μs,而是当前计时器能分辨的最小步进的线性映射。
要不要在循环里反复调用 nanoTime() 来测单次操作?
不要。哪怕只是空语句,System.nanoTime() 自身调用开销就在 10–100 纳秒量级。如果想测一个 i++ 耗时,反复调用计时函数反而让测量值远大于真实值。正确做法是:批量执行 N 次目标操作,只测一次总耗时,再除以 N;或者用 JMH 做预热+多轮采样。
真正需要微秒级反馈的场景(如高频交易 tick 处理),应优先考虑把逻辑压进更少的调用次数里,而不是靠高频率计时来“看清”单次行为——那看到的多半是计时器噪声本身。

















