Spring 工具类:StopWatch

StopWatch 是 Spring 框架提供的一个简单而强大的计时工具类,用于测量代码块的执行时间。它特别适合在开发阶段进行性能分析、调试和优化。

基本使用方法

java 复制代码
// 创建 StopWatch 实例(可指定 ID)
StopWatch stopWatch = new StopWatch("性能分析");

// 任务1 开始计时
stopWatch.start("任务1");
try {
    Thread.sleep(500); // 模拟任务执行
} finally {
    stopWatch.stop();  // 任务1 计时结束
}

// 任务2 开始计时
stopWatch.start("任务2");
try {
    Thread.sleep(1200);
} finally {
    stopWatch.stop();  // 任务2 计时结束
}

// 任务3(嵌套任务)
stopWatch.start("复杂计算");
try {
    // 子任务3.1
    stopWatch.start("矩阵运算");
    Thread.sleep(300);
    stopWatch.stop();
    
    // 子任务3.2
    stopWatch.start("向量处理");
    Thread.sleep(200);
    stopWatch.stop();
} finally {
    stopWatch.stop(); // 停止复杂计算任务
}

获取总耗时

java 复制代码
// 毫秒
long totalTimeMillis = stopWatch.getTotalTimeMillis();

// 秒
double totalTimeSeconds = stopWatch.getTotalTimeSeconds();

// 纳秒
long totalTimeNanos = stopWatch.getTotalTimeNanos();

获取单个任务耗时

java 复制代码
// 获取所有任务信息
StopWatch.TaskInfo[] tasks = stopWatch.getTaskInfo();
for (StopWatch.TaskInfo task : tasks) {
    System.out.printf("任务: %-15s 耗时: %6dms (%.1f%%)%n", 
        task.getTaskName(), 
        task.getTimeMillis(), 
        (double) task.getTimeMillis() / totalTimeMillis * 100);
}

格式化输出

java 复制代码
// 简洁输出
System.out.println(stopWatch.shortSummary());

// 格式化表格输出
System.out.println(stopWatch.prettyPrint());

输出格式如下

text 复制代码
StopWatch '性能分析': running time = 2200943100 ns
---------------------------------------------
ns         %     Task name
---------------------------------------------
0500664900  023%  任务1
1199987500  055%  任务2
0500290700  023%  复杂计算

高级用法

条件计时(可实现测试环境记时而生产环境不记时)

java 复制代码
public class ConditionalStopWatch extends StopWatch {
    private final boolean enabled;
    
    public ConditionalStopWatch(String id, boolean enabled) {
        super(id);
        this.enabled = enabled;
    }
    
    @Override
    public void start(String taskName) throws IllegalStateException {
        if (enabled) super.start(taskName);
    }
    
    @Override
    public void stop() throws IllegalStateException {
        if (enabled) super.stop();
    }
}

// 使用示例(仅在开发环境启用)
boolean isDevMode = true;
ConditionalStopWatch devWatch = new ConditionalStopWatch("开发监控", isDevMode);

使用注意事项

  • 合理命名任务:使用清晰的任务名称(如 "用户查询"、"订单处理")

  • 避免生产环境使用:StopWatch 主要用于开发调试,生产环境考虑专业 APM 工具

  • 注意嵌套任务:确保 start/stop 调用成对出现

  • 使用 try-finally:确保在异常情况下也能停止计时

完整示例

java 复制代码
public class StopWatchDemo {
    public static void main(String[] args) throws InterruptedException {
        // 创建 StopWatch 实例
        StopWatch stopWatch = new StopWatch("API 性能分析");
        
        // 模拟API处理流程
        stopWatch.start("请求解析");
        Thread.sleep(80);
        stopWatch.stop();
        
        stopWatch.start("身份验证");
        Thread.sleep(120);
        stopWatch.stop();
        
        stopWatch.start("业务处理");
        processBusinessLogic(stopWatch);
        stopWatch.stop();
        
        stopWatch.start("响应构建");
        Thread.sleep(60);
        stopWatch.stop();
        
        // 输出结果
        System.out.println("\n===== 性能分析报告 =====");
        System.out.println(stopWatch.shortSummary());
        System.out.println(stopWatch.prettyPrint());
        
        // 获取详细信息
        System.out.println("总耗时: " + stopWatch.getTotalTimeMillis() + "ms");
        System.out.println("最耗时的任务: " + stopWatch.getLastTaskName());
    }
    
    private static void processBusinessLogic(StopWatch parentWatch) throws InterruptedException {
        parentWatch.start("数据库查询");
        Thread.sleep(200);
        parentWatch.stop();
        
        parentWatch.start("数据转换");
        Thread.sleep(150);
        parentWatch.stop();
        
        parentWatch.start("缓存处理");
        Thread.sleep(100);
        parentWatch.stop();
    }
}