system.currenttimemillis()适合粗略测速,精度毫秒级,适用于接口耗时统计等场景;nanotime()高精度纳秒级但无绝对时间意义;instant+duration语义清晰但精度仍为毫秒级。

System.currentTimeMillis() 适合测代码速度吗?
适合,但只适合粗略估算;它不是为高精度计时设计的。毫秒级返回值在大多数业务耗时统计(比如接口响应时间打点、日志埋点)中完全够用,但如果你在压测里反复测 simulateBusinessMethod() 这种几十毫秒级的方法,误差可能达 ±10ms —— 因为系统时钟更新频率受限于 OS 调度和硬件 RTC 精度。
- ✅ 适用场景:记录请求开始/结束时间戳、计算数据库查询耗时(>50ms)、生成简单日志时间字段
- ❌ 不适用场景:微基准测试(JMH 场景)、纳秒级性能对比、循环内高频调用(如每轮都
System.currentTimeMillis()) - ⚠️ 常见错误:拿两次
System.currentTimeMillis()差值去判断「方法是否执行了 1.234ms」——实际你只能确定它在 [1,2] 或 [2,3] 毫秒区间内
为什么 nanoTime() 更准,却不能代替 currentTimeMillis()?
System.nanoTime() 返回的是从某个未指定起点开始的纳秒数,不关联真实时间,所以不能转成「2026-02-11 11:17」这种格式,也不能跨 JVM 进程比对。但它稳定、单调、高分辨率,是唯一能可靠测出 sub-millisecond 级别差异的 JDK 内置 API。
- ✅ 正确用法:单次测量耗时(
long start = System.nanoTime(); doWork(); long ns = System.nanoTime() - start;) - ❌ 错误用法:把
System.nanoTime()当作时间戳存库、传给前端、做定时器超时判断(它不随系统时间调整而变化) - ? 注意:
System.nanoTime()在某些虚拟化环境或老旧 CPU 上可能出现回跳(极罕见),生产环境建议搭配超时兜底逻辑
Java 8 的 Instant + Duration 怎么用才不翻车?
用 Instant.now() 和 Duration.between() 看起来很“现代”,但它们底层仍依赖 System.currentTimeMillis()(Linux/macOS 下)或 GetSystemTimeAsFileTime(Windows),所以精度仍是毫秒级,并非“自动升级到纳秒”。它的优势在于语义清晰、可读性强、支持时区无关的时间差计算。
- ✅ 推荐场景:需要输出“2分3秒124毫秒”这类可读格式、或要兼容未来可能引入的更高精度时钟抽象
- ❌ 不推荐场景:性能敏感路径(创建
Instant对象有对象分配开销)、嵌入式或内存受限环境 - ⚠️ 容易踩坑:直接用
Duration.toNanos()会溢出(最大只支持约 292 年),应优先用toMillis()或toSecondsPart()等安全方法
字符版打字练习软件里该用哪个计时方式?
如果目标是统计用户单次击键间隔、反应时间、整段练习耗时,且精度要求在 10ms 内即可(人眼/手指反应本身就有 100ms+ 延迟),那 System.currentTimeMillis() 完全够用,还省 GC 开销。但如果要做「击键延迟分布图」,想区分 16ms / 32ms / 48ms 这类渲染帧率相关阈值,就得切到 System.nanoTime()。
- ✅ 简单方案:启动练习时记
startTime = System.currentTimeMillis(),结束时算差值,显示“总用时:2分18秒” - ✅ 进阶方案:每次
KeyEvent触发时记System.nanoTime(),存入数组,后期分析抖动、P95 延迟等 - ⚠️ 关键提醒:别在 Swing/AWT 事件线程里频繁调用任何计时 API 做复杂计算,会卡 UI;先记时间戳,再异步处理
真正难的从来不是选哪个 API,而是想清楚你要回答的问题到底是什么精度、什么上下文、要不要跨进程复现——System.currentTimeMillis() 不是过时,只是被用错了地方。










