StopWatch 是 Spring 框架提供的一個簡單而強大的計時工具類,用于測量代碼塊的執行時間。它特別適合在開發階段進行性能分析、調試和優化。
基本使用方法
// 創建 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.1stopWatch.start("矩陣運算");Thread.sleep(300);stopWatch.stop();// 子任務3.2stopWatch.start("向量處理");Thread.sleep(200);stopWatch.stop();
} finally {stopWatch.stop(); // 停止復雜計算任務
}
獲取總耗時
// 毫秒
long totalTimeMillis = stopWatch.getTotalTimeMillis();// 秒
double totalTimeSeconds = stopWatch.getTotalTimeSeconds();// 納秒
long totalTimeNanos = stopWatch.getTotalTimeNanos();
獲取單個任務耗時
// 獲取所有任務信息
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);
}
格式化輸出
// 簡潔輸出
System.out.println(stopWatch.shortSummary());// 格式化表格輸出
System.out.println(stopWatch.prettyPrint());
輸出格式如下
StopWatch '性能分析': running time = 2200943100 ns
---------------------------------------------
ns % Task name
---------------------------------------------
0500664900 023% 任務1
1199987500 055% 任務2
0500290700 023% 復雜計算
高級用法
條件計時(可實現測試環境記時而生產環境不記時)
public class ConditionalStopWatch extends StopWatch {private final boolean enabled;public ConditionalStopWatch(String id, boolean enabled) {super(id);this.enabled = enabled;}@Overridepublic void start(String taskName) throws IllegalStateException {if (enabled) super.start(taskName);}@Overridepublic void stop() throws IllegalStateException {if (enabled) super.stop();}
}// 使用示例(僅在開發環境啟用)
boolean isDevMode = true;
ConditionalStopWatch devWatch = new ConditionalStopWatch("開發監控", isDevMode);
使用注意事項
-
合理命名任務:使用清晰的任務名稱(如 “用戶查詢”、“訂單處理”)
-
避免生產環境使用:StopWatch 主要用于開發調試,生產環境考慮專業 APM 工具
-
注意嵌套任務:確保 start/stop 調用成對出現
-
使用 try-finally:確保在異常情況下也能停止計時
完整示例
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();}
}