背景
你還在用 System.currentTimeMillis... 統計耗時?
比如下面這段代碼:
/**
* @author: 堆疊長
* @from: 公眾號Java技術堆疊
*/
@Test
public 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);
// 1002ms
System.out.printf("耗時:%dms.\n", sw.getTime());
更多用法
接之前的示例繼續演示,
暫停計時:
// 暫停計時
sw.suspend();
Thread.sleep(1000);
// 1000ms
System.out.printf("暫停耗時:%dms.\n", sw.getTime());
因為暫停了,所以還是 1000ms,暫停后中間休眠的 1000 ms 不會被統計,
恢復計時:
// 恢復計時
sw.resume();
Thread.sleep(1000);
// 2001ms
System.out.printf("恢復耗時:%dms.\n", sw.getTime());
因為恢復了,結果是 2001 ms,恢復后中間休眠的 1000 ms 被統計了,
停止計時:
Thread.sleep(1000);
// 停止計時
sw.stop();
Thread.sleep(1000);
// 3009ms
System.out.printf("總耗時:%dms.\n", sw.getTime());
停止計時前休眠了 1000ms,所以結果是 3009ms,停止計時后就不能再使用暫停、恢復功能了,
重置計時:
// 重置計時
sw.reset();
// 開始計時
sw.start();
Thread.sleep(1000);
// 1000ms
System.out.printf("重置耗時:%dms.\n", sw.getTime());
因為重置計時了,所以重新開始計時后又變成了 1000ms,
本文所有完整示例源代碼已經上傳:
https://github.com/javastacks/javastack
歡迎 Star 學習,后面 Java 示例都會在這上面提供!
Spring 提供的 StopWatch
來看一個簡單的例子:
// 創建一個 StopWatch 實體
StopWatch sw = StopWatch("公眾號Java技術堆疊:測驗耗時");
// 開始計時
sw.start("任務1");
// 休眠1秒
Thread.sleep(1000);
// 停止計時
sw.stop();
// 1002ms
System.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());
來看最后的輸出結果:

不過有一點不友好的是,格式化結果顯示的是納秒,而且不能修改,,
實作原理
分別來看下 commons-lang3 和 Spring 的核心原始碼:


其實也都是利用了 JDK 中的 System 系統類去實作的,做了一系列封裝而已,
總結
commons-lang3 工具包和 Spring 框架中的 StopWatch 都能輕松完成多個任務的計時以及總耗時,再也不要用手工計算耗時的方式了,手動計算如果 start 賦值錯誤可能還會出錯,
當然,以上兩個 StopWatch 的功能也遠不止堆疊長介紹的,堆疊長介紹的這些已經夠用了,更多的可以深入研究,
本文所有完整示例源代碼已經上傳:
https://github.com/javastacks/javastack
歡迎 Star 學習,后面 Java 示例都會在這上面提供!
總結一下這兩種計時工具類優缺點:
1)commons-lang3 中的 StopWatch 的用法比 Spring 中的要更簡單一些;
2)commons-lang3 中的 StopWatch 功能比 Spring 中的要更靈活、更強大一些,支持暫停、恢復、重置等功能;
3)Spring 提供每個子任務名稱,以及按格式化列印結果功能,針對多任務統計時更好一點;
綜上所述,個人推薦使用 commons-lang3 工具包中的,更靈活、更強大,如果不想額外引入包,也可以考慮 Spring 中的,根據自己的系統需求定,
所以,別再用 System.currentTimeMillis... 統計耗時了,太 low,趕緊分享轉發下吧,規范起來!
好了,今天的分享就到這里了,后面堆疊長會分享更多好玩的 Java 技術和最新的技術資訊,關注公眾號Java技術堆疊第一時間推送,我也將主流 Java 面試題和參考答案都整理好了,在公眾號后臺回復關鍵字 "面試" 進行刷題,
著作權宣告: 本文系公眾號 "Java技術堆疊" 原創,轉載、參考本文內容請注明出處,抄襲、洗稿一律投訴侵權,后果自負,并保留追究其法律責任的權利,
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2022最新版)
2.勁爆!Java 協程要來了,,,
3.Spring Boot 2.x 教程,太全了!
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!
5.《Java開發手冊(嵩山版)》最新發布,速速下載!
覺得不錯,別忘了隨手點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/494345.html
標籤:其他
上一篇:這不會又是一個Go的BUG吧?
下一篇:實體化抽象類的方法分享
