亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java實(shí)現(xiàn)代碼塊耗時(shí)測(cè)算工具類

 更新時(shí)間:2023年05月22日 10:35:42   作者:BillySir  
這篇文章主要為大家介紹了如何利用Java語言編寫一個(gè)工具類,用來測(cè)算代碼塊的耗時(shí),同時(shí)還能顯示進(jìn)度,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

1. 測(cè)算耗時(shí)

背景

程序員經(jīng)常需要知道一段代碼的執(zhí)行耗時(shí)。典型的例如查詢數(shù)據(jù)庫,不同參數(shù)查詢到不同的數(shù)據(jù)量,耗時(shí)相差很大。如果一個(gè)操作總體耗時(shí)較大,包含了幾次數(shù)據(jù)庫操作,自然就想知道哪一次操作是長耗時(shí)的主要原因,甚至每一個(gè)的耗時(shí)是多少。從而可以有的放矢地做優(yōu)化。

使用要簡單

測(cè)算一段代碼的耗時(shí),通常就是用stop watch(秒表)。在執(zhí)行的開始點(diǎn)開始計(jì)時(shí),在執(zhí)行的結(jié)束點(diǎn)停止計(jì)時(shí),并把耗時(shí)輸出到日志。雖然代碼也就幾行,但每個(gè)地方都這么寫,會(huì)顯得很啰嗦,編碼效率也低。

所以我把這個(gè)功能封裝成一個(gè)實(shí)用工具類。用起來大概是這樣子:

MonitorUtil.time(() -> {
    // 一個(gè)耗時(shí)操作,如查詢數(shù)據(jù)庫
}, "給這個(gè)操作起個(gè)名");

它會(huì)這樣輸出到日志:

[WARN] 2023-05-19T08:26:00.007 xx-project com.xxx.util.MonitorUtil 給這個(gè)操作起個(gè)名 elapsed 3,140 ms. warning

末尾的warning會(huì)在某些終端上顯示為黃色,顯眼。

輸出要簡潔

在線上運(yùn)行時(shí),也希望能知道耗時(shí)比較大的代碼。但如果每處測(cè)算耗時(shí)的地方都輸出日志,日志就會(huì)太多,而我們只關(guān)注那些長耗時(shí)。所以我規(guī)定:少于500毫秒的,不輸出。

暫停與繼續(xù)

有一種場(chǎng)景,在一個(gè)代碼范圍內(nèi),只期望計(jì)算一部分操作的累計(jì)耗時(shí),而忽略其它操作的耗時(shí)。

比如,處理一批文件,每個(gè)文件要解析后將結(jié)果存為另一個(gè)文件。這里只關(guān)心解析的時(shí)間,而忽略寫文件的耗時(shí)。所以MonitorUtil提供了暫停和繼續(xù)的功能。在寫文件時(shí),暫停計(jì)時(shí),寫文件后開始解析另一個(gè)文件時(shí)繼續(xù)計(jì)時(shí)。

最終會(huì)輸出累計(jì)的耗時(shí)以及累計(jì)等待耗時(shí)。累計(jì)等待耗時(shí),即是從暫停到繼續(xù)的時(shí)長的總和。

代碼:

MonitorUtil.time(monitor -> {
    for (...) {
        // 文件解析
        monitor.pause();
        // 其它操作
        monitor.continue();
    }
}, "僅算文件解析");

輸出如下:

[WARN] 2023-05-19T08:26:00.008 xx-project com.xxx.util.MonitorUtil 僅算文件解析 elapsed 1,140 ms,waited 2,000ms. warning
這樣就能知道那段代碼是工作的時(shí)間多還是等待的時(shí)間多了。

2. 顯示進(jìn)度

說另一個(gè)問題,也是跟時(shí)間有關(guān)的。有些功能耗時(shí)比較長,比如循環(huán)處理數(shù)據(jù)?;蛟S是10秒,或許是10分鐘。對(duì)著沒有什么輸出的屏幕,顯得很無助。此時(shí)如果能知道剩下大概需要多少時(shí)間,無疑對(duì)做決策有大幫助。如,是中斷還是繼續(xù)等。

當(dāng)然了,進(jìn)度百分比,只有業(yè)務(wù)代碼才知道。但業(yè)務(wù)代碼難以把握如何輸出這個(gè)進(jìn)度。密了則輸出一大堆,干擾視線。疏了又是漫長無助的等待。所以,是由業(yè)務(wù)代碼報(bào)告進(jìn)度,由這個(gè)工具決定要不要輸出。

代碼:

MonitorUtil.time(monitor -> {
    for (...) {
        // 一些操作
        monitor.process(proc);     // proc 是[0,1]區(qū)間的浮點(diǎn)數(shù),表示進(jìn)度
    }
}, "給這個(gè)操作起個(gè)名");

要做到輸出不能太密,不能太疏。所以MonitorUtil內(nèi)部的規(guī)則如下:

  • 5秒內(nèi)不輸出兩次
  • 5~10秒,前進(jìn)至少3%才輸出
  • 10~15秒,前進(jìn)至少1%才輸出
  • 大于15秒,無論進(jìn)度如何都輸出

這里說的多少秒,是相對(duì)于上一次輸出的時(shí)間而言。前進(jìn)也是相對(duì)于上一次輸出。

輸出:

[INFO] 2023-05-19T08:26:00.009 xx-project com.xxx.util.MonitorUtil 給這個(gè)操作起個(gè)名 7% 30% 61% 98% 100%`

嵌套使用

假如有兩個(gè)進(jìn)度測(cè)試的代碼嵌套在一起,如

MonitorUtil.time(monitor -> {
    for (...) {
        // 一些操作
        abc();
        // 一些操作
        monitor.process(proc);     // proc 是[0,1]區(qū)間的浮點(diǎn)數(shù),表示進(jìn)度
    }
}, "大功能名");

void abc() {
    MonitorUtil.time(monitor -> {
        for (...) {
            // 一些操作
            monitor.process(proc);     // proc 是[0,1]區(qū)間的浮點(diǎn)數(shù),表示進(jìn)度
        }
    }, "小功能名");
}

由于日志只有一份,兩個(gè)進(jìn)度的輸出就會(huì)混在一起,很亂,看不清。所以解決這個(gè)問題,我規(guī)定當(dāng)發(fā)生進(jìn)度測(cè)算嵌套時(shí),只有最外層的有效,即只有最外層的會(huì)輸出。好像也沒有更好的辦法了,如果您有更好的建議,請(qǐng)留言。感謝。

3. 這個(gè)工具的優(yōu)勢(shì)

高性能

  • 它的輸出都是被動(dòng)的。即只在被測(cè)代碼開始、結(jié)束、主動(dòng)調(diào)用process方法時(shí),才執(zhí)行邏輯,才有可能輸出。如果process方法沒有被調(diào)用,就算過了15秒,也不會(huì)有進(jìn)度輸出。所以,在應(yīng)用的時(shí)候,可以偏頻繁一些地調(diào)用process方法。調(diào)了不一定有輸出,不調(diào)一定不會(huì)輸出。
  • 它的內(nèi)部是順序的判斷,沒有循環(huán),更沒有復(fù)雜算法,非常高效。
  • 它并沒有創(chuàng)建新的線程(單線程),而是與業(yè)務(wù)代碼工作在同一個(gè)線程。它消耗的資源非常少,包括內(nèi)存消耗很少。在除了“開始、結(jié)束、process方法被調(diào)用時(shí)”之外,消耗的CPU為零。用它來測(cè)算時(shí)間,成本極低,可以大量使用。

支持異常

業(yè)務(wù)代碼發(fā)生異常時(shí),它還能不能測(cè)算出耗時(shí)?可以的?;卣{(diào)方法(lambda表達(dá)式)如果發(fā)生的異常,它也能計(jì)算耗時(shí),并在耗時(shí)超過500毫秒時(shí)輸出。異常也是結(jié)束的一種。

測(cè)算的目標(biāo)形式

如前面所見,它測(cè)算的目標(biāo)形式是代碼塊,而代碼塊是最靈活的表現(xiàn)形式。它可以是一行代碼,可以是多行。可以是一個(gè)函數(shù)的完整代碼,也可以是函數(shù)的一部分代碼。

4. 實(shí)現(xiàn)原理簡介

它的內(nèi)部實(shí)現(xiàn)原理并不難。測(cè)算時(shí)間,就是記錄(用變量保存)開始時(shí)間,并在結(jié)束時(shí)計(jì)算一下時(shí)間差。進(jìn)度功能,則是記錄上一次的輸出時(shí)間和進(jìn)度,下次輸出時(shí)作對(duì)比。暫停功能,則是用兩個(gè)變量分別記錄工作和等待的耗時(shí)累加值。至于如何知道自己是不是“最外層”,則是用一個(gè)static變量來保存當(dāng)前的層數(shù)。如果是0就是最外層。

它的每一處實(shí)現(xiàn),都是平淡無奇。借用棋類的話,就是“通盤無妙手”。關(guān)鍵是實(shí)用。

到此這篇關(guān)于Java實(shí)現(xiàn)代碼塊耗時(shí)測(cè)算工具類的文章就介紹到這了,更多相關(guān)Java代碼耗時(shí)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot cloud使用eureka整合分布式事務(wù)組件Seata 的方法

    springboot cloud使用eureka整合分布式事務(wù)組件Seata 的方法

    這篇文章主要介紹了springboot cloud使用eureka整合分布式事務(wù)組件Seata 的方法 ,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-05-05
  • Spring Boot 通過CORS實(shí)現(xiàn)跨域問題

    Spring Boot 通過CORS實(shí)現(xiàn)跨域問題

    這篇文章主要介紹了Spring Boot 通過CORS實(shí)現(xiàn)跨域,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Nacos集群模式下服務(wù)無法注冊(cè)問題

    Nacos集群模式下服務(wù)無法注冊(cè)問題

    這篇文章主要介紹了Nacos集群模式下服務(wù)無法注冊(cè)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java中的while無限循環(huán)結(jié)構(gòu)及實(shí)例

    Java中的while無限循環(huán)結(jié)構(gòu)及實(shí)例

    這篇文章主要介紹了Java中的while無限循環(huán)結(jié)構(gòu)及實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Java設(shè)計(jì)模式之工廠模式分析【簡單工廠、工廠方法、抽象工廠】

    Java設(shè)計(jì)模式之工廠模式分析【簡單工廠、工廠方法、抽象工廠】

    這篇文章主要介紹了Java設(shè)計(jì)模式之工廠模式,結(jié)合實(shí)例形式分析了簡單工廠、工廠方法、抽象工廠等相關(guān)功能、實(shí)現(xiàn)與使用方法,需要的朋友可以參考下
    2018-04-04
  • java面向?qū)ο缶幊填惖膬?nèi)聚性分析

    java面向?qū)ο缶幊填惖膬?nèi)聚性分析

    高內(nèi)聚、低耦合是軟件設(shè)計(jì)中非常關(guān)鍵的概念。在面向?qū)ο蟪绦蛟O(shè)計(jì)中類的劃分時(shí),類的內(nèi)聚性越高,其封裝性越好,越容易復(fù)用
    2021-10-10
  • 你不知道的 IDEA Debug調(diào)試小技巧(小結(jié))

    你不知道的 IDEA Debug調(diào)試小技巧(小結(jié))

    這篇文章主要介紹了你不知道的 IDEA Debug調(diào)試小技巧(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • SpringBoot開發(fā)實(shí)戰(zhàn)系列之動(dòng)態(tài)定時(shí)任務(wù)

    SpringBoot開發(fā)實(shí)戰(zhàn)系列之動(dòng)態(tài)定時(shí)任務(wù)

    在我們?nèi)粘5拈_發(fā)中,很多時(shí)候,定時(shí)任務(wù)都不是寫死的,而是寫到數(shù)據(jù)庫中,從而實(shí)現(xiàn)定時(shí)任務(wù)的動(dòng)態(tài)配置,下面這篇文章主要給大家介紹了關(guān)于SpringBoot開發(fā)實(shí)戰(zhàn)系列之動(dòng)態(tài)定時(shí)任務(wù)的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • java多線程編程之使用thread類創(chuàng)建線程

    java多線程編程之使用thread類創(chuàng)建線程

    在Java中創(chuàng)建線程有兩種方法:使用Thread類和使用Runnable接口。在使用Runnable接口時(shí)需要建立一個(gè)Thread實(shí)例
    2014-01-01
  • 通過Java實(shí)現(xiàn)自己動(dòng)手寫ls命令

    通過Java實(shí)現(xiàn)自己動(dòng)手寫ls命令

    在前面的文章中,我們仔細(xì)的介紹了關(guān)于ls命令的使用和輸出結(jié)果,在本篇文章當(dāng)中我們用Java代碼自己實(shí)現(xiàn)ls命令,更加深入的了解ls命令
    2022-10-10

最新評(píng)論