System.currentTimeMillis()精度通常为10–15ms,由操作系统和硬件决定,非Java自身控制;它调用系统壁钟接口,受内核时钟源、timer tick及虚拟化影响,无法稳定达毫秒级,故只适用于粗粒度计时。

System.currentTimeMillis() 的系统时钟精度不是 Java 自身决定的,而是由底层操作系统和硬件时钟提供,通常在 10–15 毫秒量级。Windows 上往往更差(可能达 15–55ms),Linux 和 macOS 一般稍好(常见 10–15ms),但绝非毫秒级“稳定输出”,更不是纳秒或微秒级精度。
它为什么做不到真正毫秒级分辨?
关键在于:它调用的是操作系统级时间接口(如 Linux 的 gettimeofday() 或 Windows 的 GetSystemTimeAsFileTime()),而这些接口本身受制于内核时钟源、调度器滴答(timer tick)、vDSO 优化程度以及硬件计时器能力。现代系统虽普遍支持高分辨率时钟(如 Linux 的 CLOCK_MONOTONIC),但 currentTimeMillis() 为兼容性和稳定性,默认走的是“壁钟”路径,并不强制绑定最高精度时钟源。
- Windows 默认 timer resolution 为 15.625ms(64Hz),除非显式调用
timeBeginPeriod(1)提升,否则无法稳定达到 1ms - Linux 在多数发行版中,
gettimeofday()基于CLOCK_REALTIME,其实际抖动取决于内核配置与硬件——即使标称“微秒级”,Java 层连续两次调用仍常返回相同值 - 虚拟机环境(尤其是云主机)会进一步放大不确定性:Hypervisor 时间虚拟化、CPU 抢占、vCPU 频率波动都会导致时间戳跳跃或停滞
精度不足带来的典型现象
你看到的“0ms 耗时”,大概率不是代码真的没花时间,而是两次调用落在了同一个时钟滴答周期内。这不是 bug,是设计使然。
- 执行一个空循环或简单赋值,测出耗时恒为 0 —— 实际可能花了几十纳秒,但系统根本“看不见”
- 同一段代码多次运行,耗时在 0/15/31ms 之间跳变,而非平滑分布
- 日志里相邻两条记录时间戳相同(尤其高并发打点时),导致排序、聚合、P95 计算失真
如何验证你环境的真实精度?
别依赖文档,实测最可靠。一段轻量探测代码就能揭示真相:
(注意:需在目标生产环境 JVM 下运行,避免开发机干扰)- 连续调用 10000 次
System.currentTimeMillis(),统计不同值出现的频次 —— 若绝大多数结果重复,说明分辨率低 - 用
System.nanoTime()做参照:在currentTimeMillis()返回相同值的区间内,nanoTime()差值是否稳定增长?若增长明显,说明毫秒时钟“卡住”了 - 观察系统
dmesg | grep -i clock(Linux)或systeminfo | findstr "System Boot Time"(Windows)确认时钟源是否启用 HPET 或 TSC
该精度下哪些事能做、哪些不能做?
接受它的边界,才能用得稳。
- ✅ 可靠用于:接口整体响应打点(>100ms 场景)、任务生命周期记录、日志时间戳(毫秒级可读性足够)、粗粒度超时控制(如 30 秒连接超时)
- ❌ 不适合:算法微基准对比、熔断阈值判定(如 50ms 熔断)、高频防抖(Android 点击 300ms 限制)、SLA 细粒度达标分析、链路各环节拆分耗时

















