System.currentTimeMillis() 不适用于精确计时,因其返回墙上时间而非单调递增的执行时间,导致超时控制失效、防抖失灵、性能统计失真、采样错序及跨系统耗时误判。

System.currentTimeMillis() 的误差不是代码写错了,而是它根本就不是为精确计时设计的——它返回的是“墙上时间”,不是“执行时间”。一旦用它做耗时判断、超时控制或顺序约束,业务逻辑就容易在特定条件下突然失灵。
超时控制可能直接失效
比如串口通信设了 500ms 超时,若系统时间被回拨 2 秒,end - start 会算出负值,立刻触发假超时;反之若 NTP 向前同步跳了 1 秒,本该超时的请求反而继续执行,导致资源堆积或状态错乱。
- 防抖逻辑(如按钮点击限制 300ms)在用户手动改系统时间后彻底瘫痪
- RPC 客户端等待响应时,误判服务端慢,实则是本地时钟跳变
- 订单支付倒计时出现“跳秒”“回退”甚至卡死,因时间戳不再单调
性能统计严重失真
单次调用真实耗时 8μs,但 currentTimeMillis() 分辨率只有 10–16ms,结果恒为 0;高并发下还可能因底层锁竞争,100 次调用耗时比创建 HashMap 还长。
- 压测报告里大量“0ms”接口,掩盖真实瓶颈
- 同一段代码在 Windows 和 Linux 上测出相差一个数量级的“耗时”
- GC 暂停、线程调度延迟、IO 阻塞全被计入“业务耗时”,误导优化方向
环形缓冲与采样顺序错乱
某些实时采集系统要求时间戳严格递增,用于排序或滑动窗口计算。currentTimeMillis() 在 NTP 校时或虚拟机恢复时可能重复、相等甚至倒退,导致样本错序、窗口计算错误、数据丢弃或重复处理。
- 传感器数据按时间戳入库,出现“后写入的数据时间更早”
- 消息队列消费位点回滚,因时间戳倒退被误判为旧消息
- 限流器窗口计数异常,同一秒内多个请求被分到不同时间桶
跨系统调用时混淆真实耗时
HTTP 请求耗时统计里混入了 DNS 解析延迟、连接复用等待、线程抢占、GC STW 等非业务因素。它测的不是“代码跑多久”,而是“从开始到结束之间墙上的时间差”。
- 服务端响应仅需 2ms,客户端却报出 47ms —— 实际是线程被调度延迟了 45ms
- 数据库查询快,但连接池拿连接花了 200ms,却被归为 SQL 执行慢
- 熔断阈值设为 100ms,结果因系统时间跳变频繁误熔断

















