告别System.currentTimeMillis()!Java高精度计时最佳实践

关注我的公众号:【编程朝花夕拾】,可获取首发内容。

01 引言

开过过程中,经常会遇到一些耗时的方法。当我们需要定位耗时的方法时,就需要逐步打印耗时已确认耗时的方法。或者在写单元测试的时候,粗略的估算方法耗时,是不是经常使用System.currentTimeMillis()去计算的。

今天,我们一起来整理一下可以使用那些方法计算耗时。

02 耗时计算方案

我们先罗列出常用的计算耗时的方法。我们需要模拟一个方法的耗时:

java 复制代码
private void invokeMethod() {
    try {
        System.out.println(DateUtil.now() + " invokeMethod 方法执行中......");
        // 模拟方法耗时:0~3000 ms
        Thread.sleep(new Random().nextLong(3000));
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
}

2.1 System.currentTimeMillis()

System.currentTimeMillis()毫秒级计算。

java 复制代码
@Test
void test01() {
    long start = System.currentTimeMillis();
    invokeMethod();
    long end = System.currentTimeMillis();
    System.out.println(DateUtil.now() + " 执行完毕,耗时:" + (end - start) + "ms");
    
    // 结果
    /*
     * 2025-07-11 14:19:55 invokeMethod 方法执行中......
     * 2025-07-11 14:19:58 执行完毕,耗时:2421ms
     */
}

2.2 System.nanoTime()

System.nanoTime() 纳秒级计算,计算方式和 System.currentTimeMillis()一致。

java 复制代码
@Test
void test02() {
    long start = System.nanoTime();
    invokeMethod();
    long end = System.nanoTime();
    System.out.println(DateUtil.now() + " 执行完毕,耗时:" + (end - start) + "ns");
}

2.3 Java8 InstantDuration

java 复制代码
@Test
void test03() {
    Instant start = Instant.now();
    invokeMethod();
    Instant end = Instant.now();
    System.out.println(DateUtil.now() + " 执行完毕,耗时:" + Duration.between(start, end).toMillis() + "ms");
}

2.4 Spring框架StopWatch

java 复制代码
@Test
void test04() {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    invokeMethod();
    stopWatch.stop();
    System.out.println(DateUtil.now() + " 执行完毕,耗时:" + stopWatch.getTotalTimeMillis() + "ms");
}

2.5 ApacheStopWatch

java 复制代码
@Test
void test05() {
    org.apache.commons.lang3.time.StopWatch stopWatch = new org.apache.commons.lang3.time.StopWatch();
    stopWatch.start();
    invokeMethod();
    stopWatch.stop();
    System.out.println(DateUtil.now() + " 执行完毕,耗时:" + stopWatch.getTime() + "ms");
}

2.6 hutoolStopWatch

java 复制代码
@Test
void test06() {
    cn.hutool.core.date.StopWatch stopWatch = new cn.hutool.core.date.StopWatch();
    stopWatch.start();
    invokeMethod();
    stopWatch.stop();
    System.out.println(DateUtil.now() + " 执行完毕,耗时:" + stopWatch.getTotalTimeMillis() + "ms");
}

2.7 GoogleStopwatch

这里要注意的是GoogleStopwatch中的watch为小写。

java 复制代码
@Test
void test06() {
    Stopwatch stopWatch = Stopwatch.createUnstarted();
    stopWatch.start();
    invokeMethod();
    stopWatch.stop();
    System.out.println(DateUtil.now() + " 执行完毕,耗时:" + stopWatch.elapsed().toMillis() + "ms");
}

2.8 阿里的Arthas

Arthas作为一款在线的Java诊断工具,被用作生产环境。和其他计算工具不同的是,这种方式没有代码的侵入性,启动Arthas后执行命令后,等待方法执行即可。

方法

java 复制代码
@RestController
public class TimeController {

    @RequestMapping("/test")
    public void test() {
        try {
            System.out.println(DateUtil.now() + " invokeMethod 方法执行中......");
            Thread.sleep(new Random().nextLong(3000));
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

启动Arthas

选择当前运行的项目编号:

输入命令

sh 复制代码
trace com.simonking.boot.tool.controller.TimeController test  -n 5 --skipJDKMethod false 

运行方法

03 技术选型

耗时的计算用作测试,任意选择都无所谓,只要能达到目的即可。

  • 2.12.3用作单任务的耗时计算
  • 2.42.7用于复杂 的分段计算,无需不断的创建时间点,只需要重新调用start()方法即可,个别框架apache调用之前需要reset()重置之后方可使用。
  • 2.8用于生产问题的定位,可以观察每一段代码的耗时

04 小结

通过合理选择计时方法,可以更准确地获取代码性能数据,帮助优化关键路径逻辑。

相关推荐
gb42152872 分钟前
java中将租户ID包装为JSQLParser的StringValue表达式对象,JSQLParser指的是?
java·开发语言·python
曾经的三心草13 分钟前
Python2-工具安装使用-anaconda-jupyter-PyCharm-Matplotlib
android·java·服务器
Metaphor69213 分钟前
Java 高效处理 Word 文档:查找并替换文本的全面指南
java·经验分享·word
ChinaRainbowSea28 分钟前
7. LangChain4j + 记忆缓存详细说明
java·数据库·redis·后端·缓存·langchain·ai编程
舒一笑28 分钟前
同步框架与底层消费机制解决方案梳理
后端·程序员
stormsha28 分钟前
飞算JavaAI炫技赛电商系统商品管理模块的架构设计与实现
java·架构·鸿蒙系统
minh_coo29 分钟前
Spring框架事件驱动架构核心注解之@EventListener
java·后端·spring·架构·intellij-idea
翻滚丷大头鱼38 分钟前
Java 集合Collection—List
java·开发语言
敲键盘的肥嘟嘟左卫门1 小时前
StringBuilder类的数据结构和扩容方式解读
java
索迪迈科技2 小时前
java后端工程师进修ing(研一版 || day40)
java·开发语言·学习·算法