背景
你還在用 System.currentTimeMillis... 統計耗時?
比如下面這段代碼:
/** * @author: 棧長 * @from: 公眾號Java技術棧 */@Testpublic void JDKWasteTime() throws InterruptedException { long start = System.currentTimeMillis(); Thread.sleep(3000); System.out.printf("耗時:%dms.", System.currentTimeMillis() - start);}
System.currentTimeMillis...這種方式統計耗時確實是用的最多的,因為它不用引入其他的 JAR 包,JDK 就能搞定,但是它用起來有幾個不方便的地方:
1)需要定義初始時間值,再用當前時間進行手工計算;
2)統計多個任務的耗時比較麻煩,如果 start 賦值搞錯可能還會出現邏輯問題;
有沒有其他的更好的替代方案呢?答案是肯定的:StopWatch!
StopWatch
StopWatch 是一個統計耗時的工具類:
常用的 StopWatch 工具類有以下兩種:
- commons-lang3(Apache 提供的通用工具包)
- spring-core(Spring 核心包)
雖然兩個工具類的名稱是一樣的,但是用法大不相同,本文棧長就給大家分別演示下。
commons-lang3 提供的 StopWatch
引入依賴
commons-lang3 是 Apache 開源的通用工具包,需要額外引入 Maven 依賴:
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>${commons-lang3.version}</version></dependency>
簡單示例
創建一個 StopWatch 實例有以下 3 種方法:
1) 使用 new 關鍵字
StopWatch sw = new StopWatch();
2)使用 create 工廠方法
StopWatch sw = StopWatch.create();
3)使用 createStarted 方法
StopWatch sw = StopWatch.createStarted();
這個方法不但會創建一個實例,同時還會啟動計時。
來看一個簡單的例子:
// 創建一個 StopWatch 實例並開始計時StopWatch sw = StopWatch.createStarted();// 休眠1秒Thread.sleep(1000);// 1002msSystem.out.printf("耗時:%dms.\n", sw.getTime());
更多用法
接之前的示例繼續演示。
暫停計時:
// 暫停計時sw.suspend();Thread.sleep(1000);// 1000msSystem.out.printf("暫停耗時:%dms.\n", sw.getTime());
因為暫停了,所以還是 1000ms,暫停後中間休眠的 1000 ms 不會被統計。
恢復計時:
// 恢復計時sw.resume();Thread.sleep(1000);// 2001msSystem.out.printf("恢復耗時:%dms.\n", sw.getTime());
因為恢復了,結果是 2001 ms,恢復後中間休眠的 1000 ms 被統計了。
停止計時:
Thread.sleep(1000);// 停止計時sw.stop();Thread.sleep(1000);// 3009msSystem.out.printf("總耗時:%dms.\n", sw.getTime());
停止計時前休眠了 1000ms,所以結果是 3009ms,停止計時後就不能再使用暫停、恢復功能了。
重置計時:
// 重置計時sw.reset();// 開始計時sw.start();Thread.sleep(1000);// 1000msSystem.out.printf("重置耗時:%dms.\n", sw.getTime());
因為重置計時了,所以重新開始計時後又變成了 1000ms。
本文所有完整示例原始碼已經上傳:
https://github.com/javastacks/javastack
歡迎 Star 學習,後面 Java 示例都會在這上面提供!另外,最新面試題整理好了,大家可以在Java面試庫小程序在線刷題。
Spring 提供的 StopWatch
來看一個簡單的例子:
// 創建一個 StopWatch 實例StopWatch sw = StopWatch("公眾號Java技術棧:測試耗時");// 開始計時sw.start("任務1");// 休眠1秒Thread.sleep(1000);// 停止計時sw.stop();// 1002msSystem.out.printf("任務1耗時:%d%s.\n", sw.getLastTaskTimeMillis(), "ms");
Spring 創建實例的方法就是 new,開始計時,以及獲取時間需要手動 start、stop。
繼續再新增 2 個任務:
Thread.sleep(1000);sw.start("任務2");Thread.sleep(1100);sw.stop();// 1100ms.System.out.printf("任務2耗時:%d%s.\n", sw.getLastTaskTimeMillis(), "ms");sw.start("任務3");Thread.sleep(1200);sw.stop();// 1203ms.System.out.printf("任務3耗時:%d%s.\n", sw.getLastTaskTimeMillis(), "ms");// 3.309373456s.System.out.printf("任務數量:%s,總耗時:%ss.\n", sw.getTaskCount(), sw.getTotalTimeSeconds());
Spring 一個重要的亮點是支持格式化列印結果:
System.out.println(sw.prettyPrint());
來看最後的輸出結果:
不過有一點不友好的是,格式化結果顯示的是納秒,而且不能修改。