商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > System.currentTimeMillis与System.nanoTime的区别与应用场景

System.currentTimeMillis与System.nanoTime的区别与应用场景

  发布于2026-07-09 阅读(0)

扫一扫,手机访问

在 Java 开发中,时间处理是绕不开的话题。很多新手甚至老手都会在 System.currentTimeMillis()System.nanoTime() 之间犯迷糊。简单一句话总结就是:测代码跑多快,用 nanoTime;记时间点、设超时、存时间戳,用 currentTimeMillis。两者起点不同、单位不同、目标不同,绝对不能混用。

System.currentTimeMillis与System.nanoTime的区别与应用场景

先放个大原则:测代码执行时间,只用 nanoTime;记日志、设超时、存时间戳,则靠 currentTimeMillis。两者从一开始就是为不同场景设计的,混用只会带来隐蔽的 bug。

测代码执行时间,只用 nanoTime

System.nanoTime() 本质上是一个单调递增的计数器,专为测量“过了多久”而生。它不受系统时间调整的影响——无论是手动改时间、NTP 同步还是闰秒,都不会让它出现负值或跳变。它的返回值是纳秒级别,在 Linux/macOS 上实际分辨率常达到纳秒级,Windows 上约为 100 纳秒,这远高于毫秒级的 currentTimeMillis

使用时有几点值得注意:

  • 只做差值计算,别关心它的绝对值。比如用 startTimeendTime 相减就行。
  • 转毫秒时要除以 1_000_000.0,而不是简单的 1000
  • 单次测量的意义有限,建议批量运行(比如 1000 次以上)并取中位数,这样可以避开 JIT 预热和 GC 的干扰。
  • 别在高频循环里反复调用,计时本身也会干扰热点路径的性能。

记录时间点、判断超时,用 currentTimeMillis

System.currentTimeMillis() 对应的是 Unix 时间戳,表示自 1970-01-01 UTC 起的毫秒数。它能直接转成 DateLocalDateTime 或 ISO 格式,非常适合人类可读、数据库存储、订单号生成、任务调度等场景。

它的适用场景包括:

  • 写日志时打上“现在几点”的时间戳。
  • 设置连接超时,比如“5 秒未响应则断开”。
  • 计算有效期,比如 token 过期时间 = 当前时间 + 3600000。
  • 与外部系统按标准时间对齐,比如 HTTP Date 头或数据库时间字段。

需要注意的是,它不适合测短耗时,因为两次调用可能返回相同的值。如果业务对时钟稳定性要求极高(比如金融撮合),最好配合 NTP 监控或硬件校准。

绝对不能混用的典型错误

两者数值之间没有数学关系,交叉使用会引入隐蔽的 bug:

  • 别用 nanoTime() 做定时调度(比如“10 秒后发通知”),它不映射真实时间点。
  • 别拿 currentTimeMillis()nanoTime(),结果毫无意义。
  • 别把 nanoTime() 的值传给 Thread.sleep()ScheduledExecutorService
  • 别把 nanoTime() 的绝对值当时间戳存库或打印日志。

性能与精度的现实考量

从性能上看,currentTimeMillis() 在 Windows 上的调用开销略低(约 25ns vs nanoTime 的 50ns),但其毫秒级分辨率在多数性能敏感场景下反而成了瓶颈。比如游戏帧率控制(16ms/帧)、锁竞争分析、微基准测试等,都依赖 nanoTime() 的稳定性和高分辨率。

如果需要高频低开销的时间戳(比如大量日志打点),可以考虑封装一个定期刷新的 CachedClock,容忍几十毫秒的误差,这样能在效率和可用性之间找到平衡。

本文转载于:https://www.php.cn/faq/2793698.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注