Java簡(jiǎn)單方法實(shí)現(xiàn)子任務(wù)耗時(shí)統(tǒng)計(jì)
背景
在并發(fā)編程中,我們經(jīng)常需要將一個(gè)大任務(wù)拆分成多個(gè)子任務(wù)并行執(zhí)行。但隨之而來(lái)的問(wèn)題是:如何準(zhǔn)確統(tǒng)計(jì)每個(gè)子任務(wù)的耗時(shí)?
傳統(tǒng)的做法是在業(yè)務(wù)代碼中手動(dòng)埋點(diǎn),但這樣會(huì)導(dǎo)致代碼侵入性強(qiáng)、難以維護(hù)。本文介紹一種基于裝飾器模式的優(yōu)雅實(shí)現(xiàn)方案。
核心思路
通過(guò)包裝 Callable 接口,在任務(wù)執(zhí)行前后自動(dòng)記錄時(shí)間戳,實(shí)現(xiàn)對(duì)任務(wù)生命周期各階段的監(jiān)控:
Timeline: submitTime -> startTime -> endTime
| | |
+-- 等待時(shí)間 --+-- 執(zhí)行時(shí)間 --+
| |
+------- 總耗時(shí) -----------+
代碼實(shí)現(xiàn)
1. 定義時(shí)間記錄字段
public class ScopedCallable<V> implements Callable<V> {
private static final long NANO_TO_MS = 1_000_000L;
/** 任務(wù)名稱(chēng) */
private final String taskName;
/** 被包裝的實(shí)際任務(wù) */
private final Callable<V> delegate;
/** 任務(wù)提交時(shí)間 (納秒) */
private final long submitTime;
/** 任務(wù)開(kāi)始執(zhí)行時(shí)間 (納秒) */
private long startTime;
/** 任務(wù)執(zhí)行結(jié)束時(shí)間 (納秒) */
private long endTime;
}
2. 在構(gòu)造函數(shù)中記錄提交時(shí)間
public ScopedCallable(String taskName, Callable<V> delegate) {
this.taskName = Objects.requireNonNull(taskName);
this.delegate = Objects.requireNonNull(delegate);
this.submitTime = System.nanoTime(); // 記錄提交時(shí)間
}
3. 在 call() 方法中記錄執(zhí)行時(shí)間
@Override
public V call() throws Exception {
try {
startTime = System.nanoTime(); // 記錄開(kāi)始時(shí)間
return delegate.call(); // 執(zhí)行實(shí)際任務(wù)
} finally {
endTime = System.nanoTime(); // 記錄結(jié)束時(shí)間
reportMetrics(); // 上報(bào)監(jiān)控指標(biāo)
}
}
4. 計(jì)算各階段耗時(shí)
/** 執(zhí)行耗時(shí) = 結(jié)束時(shí)間 - 開(kāi)始時(shí)間 */
public long executionTime() {
return endTime - startTime;
}
/** 等待耗時(shí) = 開(kāi)始時(shí)間 - 提交時(shí)間 */
public long waitTime() {
return startTime - submitTime;
}
/** 總耗時(shí) = 結(jié)束時(shí)間 - 提交時(shí)間 */
public long totalTime() {
return endTime - submitTime;
}
5. 上報(bào)監(jiān)控指標(biāo)
private void reportMetrics() {
long execMs = executionTime() / NANO_TO_MS;
long waitMs = waitTime() / NANO_TO_MS;
long totalMs = totalTime() / NANO_TO_MS;
System.out.println("[" + taskName + "] 執(zhí)行耗時(shí): " + execMs + "ms");
System.out.println("[" + taskName + "] 等待耗時(shí): " + waitMs + "ms");
System.out.println("[" + taskName + "] 總耗時(shí): " + totalMs + "ms");
}
設(shè)計(jì)要點(diǎn)
| 要點(diǎn) | 說(shuō)明 |
|---|---|
| 納秒精度 | 使用 System.nanoTime() 而非 currentTimeMillis(),精度更高且不受系統(tǒng)時(shí)鐘調(diào)整影響 |
| finally 塊 | 確保即使任務(wù)拋異常也能記錄結(jié)束時(shí)間 |
| 透明包裝 | 對(duì)業(yè)務(wù)代碼無(wú)侵入,只需在提交任務(wù)時(shí)包裝一層 |
使用示例
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(2);
// 提交包裝后的任務(wù)
Future<String> future = executor.submit(
new ScopedCallable<>("queryDB", () -> {
Thread.sleep(100); // 模擬耗時(shí)操作
return "result";
})
);
System.out.println("結(jié)果: " + future.get());
executor.shutdown();
}
輸出示例:
[queryDB] 執(zhí)行耗時(shí): 102ms
[queryDB] 等待耗時(shí): 0ms
[queryDB] 總耗時(shí): 102ms
結(jié)果: result
總結(jié)
通過(guò)裝飾器模式包裝 Callable,可以?xún)?yōu)雅地實(shí)現(xiàn):
- 提交時(shí)間、等待時(shí)間、執(zhí)行時(shí)間 的自動(dòng)采集
- 監(jiān)控指標(biāo) 的自動(dòng)上報(bào)
這種方案的核心優(yōu)勢(shì)是零侵入——業(yè)務(wù)代碼無(wú)需修改,只需在任務(wù)提交處統(tǒng)一包裝即可。
到此這篇關(guān)于Java簡(jiǎn)單方法實(shí)現(xiàn)子任務(wù)耗時(shí)統(tǒng)計(jì)的文章就介紹到這了,更多相關(guān)Java統(tǒng)計(jì)任務(wù)耗時(shí)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaEE Filter敏感詞過(guò)濾的方法實(shí)例詳解
我們無(wú)論是在聊天還是在留言時(shí),都有一些信息不希望別人看到。那么如果過(guò)濾這些關(guān)鍵詞呢?下面小編給大家分享JavaEE Filter敏感詞過(guò)濾的方法實(shí)例詳解,感興趣的朋友一起學(xué)習(xí)吧2016-05-05
JMeter中的后端監(jiān)聽(tīng)器的實(shí)現(xiàn)
本文主要介紹了JMeter中的后端監(jiān)聽(tīng)器的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
Spring整合WebSocket應(yīng)用示例(上)
以下教程是小編在參與開(kāi)發(fā)公司的一個(gè)crm系統(tǒng),整理些相關(guān)資料,在該系統(tǒng)中有很多消息推送功能,在其中用到了websocket技術(shù)。下面小編整理分享到腳本之家平臺(tái)供大家參考2016-04-04
解決spring boot環(huán)境切換失效的問(wèn)題
這篇文章主要介紹了解決spring boot環(huán)境切換失效的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
Java Object類(lèi)方法原理和使用場(chǎng)景
本文詳細(xì)介紹了Java中Object類(lèi)的幾個(gè)重要方法,包括clone()、getClass()、toString()、finalize()、equals()和hashCode(),以及wait()、notify()、notifyAll(),每個(gè)方法的使用場(chǎng)景、特點(diǎn)和最佳實(shí)踐都被逐一解釋,感興趣的朋友跟隨小編一起看看吧2025-11-11
Java 實(shí)現(xiàn)repalceAll只替換第二個(gè)匹配到的字符串
這篇文章主要介紹了Java 實(shí)現(xiàn)repalceAll只替換第二個(gè)匹配到的字符串,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12
基于mybatis-plus QueryWrapper 排序的坑
這篇文章主要介紹了mybatis-plus QueryWrapper 排序的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01

