国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Apache和Spring提供的StopWatch執(zhí)行時(shí)間監(jiān)視器

Genng / 1193人閱讀

摘要:借助它來(lái)統(tǒng)計(jì)我們程序的執(zhí)行時(shí)間,帶給非常多的方便和優(yōu)雅。且,且,且設(shè)置為了當(dāng)前時(shí)間。

相關(guān)閱讀

【小家java】java5新特性(簡(jiǎn)述十大新特性) 重要一躍
【小家java】java6新特性(簡(jiǎn)述十大新特性) 雞肋升級(jí)
【小家java】java7新特性(簡(jiǎn)述八大新特性) 不溫不火
【小家java】java8新特性(簡(jiǎn)述十大新特性) 飽受贊譽(yù)
【小家java】java9新特性(簡(jiǎn)述十大新特性) 褒貶不一
【小家java】java10新特性(簡(jiǎn)述十大新特性) 小步迭代
【小家java】java11新特性(簡(jiǎn)述八大新特性) 首個(gè)重磅LTS版本

前言

編碼過(guò)程中我們經(jīng)常會(huì)希望得到一段代碼(一個(gè)方法)的執(zhí)行時(shí)間,本文將介紹兩種時(shí)間監(jiān)視器(秒表)來(lái)讓你優(yōu)雅的、靈活的處理這個(gè)問(wèn)題。

Java源生方式

這種方式最最簡(jiǎn)單,最好理解,當(dāng)然也是最為常用:我們自己書(shū)寫(xiě)。
例如:我們?nèi)绻y(tǒng)計(jì)一段代碼的執(zhí)行時(shí)間,經(jīng)常會(huì)這么來(lái)寫(xiě):

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();   //獲取開(kāi)始時(shí)間

        //函數(shù)主體代碼
        //...

        long endTime = System.currentTimeMillis(); //獲取結(jié)束時(shí)間
        System.out.println("程序運(yùn)行時(shí)間: " + (endTime - startTime) + "ms");
    }

大多數(shù)時(shí)候我們使用ms來(lái)表示即可,但是這么寫(xiě)缺乏靈活性。倘若我們要展示成納秒、秒、甚至分鐘,還得我們自己處理(把毫秒值拿來(lái)進(jìn)行轉(zhuǎn)換~ )

當(dāng)然可能到了JDK8以后,我們這么做能變得稍微靈活一些:可以這么處理:

    public static void main(String[] args) {
        Instant start = Instant.now();
        //doSomething();
        Instant end = Instant.now();

        Duration duration = Duration.between(start, end);
        System.out.println("millis = " + duration.toMillis());
    }

這個(gè)比上面靈活度強(qiáng)一些。但也還是有一定的缺點(diǎn):步驟稍顯復(fù)雜,總體上還是不夠優(yōu)雅,也不是那么的靈活。
那么本文針對(duì)此問(wèn)題介紹一個(gè)工具:StopWatch執(zhí)行時(shí)間監(jiān)視器。借助它來(lái)統(tǒng)計(jì)我們程序的執(zhí)行時(shí)間,帶給非常多的方便和優(yōu)雅。

StopWatch需要依賴額外的Jar:commons-lang3或者spring-core,但因這兩個(gè)Jar是Java開(kāi)發(fā)中都必導(dǎo)的,因此依賴兼容性方面可以忽略

StopWatch有很多開(kāi)源的框架都有提供類似的功能:比如Apache的commons-lang3,當(dāng)然還有Spring framwork自己提供的,本文將針對(duì)此倆分別做介紹~

Commons-lang3的StopWatch

Apache提供的這個(gè)任務(wù)執(zhí)行監(jiān)視器功能豐富強(qiáng)大(比Spring的強(qiáng)大),靈活性強(qiáng),如下經(jīng)典實(shí)用案例:

    public static void main(String[] args) throws Exception {
        StopWatch watch = StopWatch.createStarted(); //創(chuàng)建后立即start,常用
        //StopWatch watch = new StopWatch();
        //watch.start();

        Thread.sleep(1000);
        System.out.println("統(tǒng)計(jì)從開(kāi)始到現(xiàn)在運(yùn)行時(shí)間:" + watch.getTime() + "ms"); //1000ms

        Thread.sleep(1000);
        watch.split();
        System.out.println("從start到此刻為止的時(shí)間:" + watch.getTime());
        System.out.println("從開(kāi)始到第一個(gè)切入點(diǎn)運(yùn)行時(shí)間:" + watch.getSplitTime()); //2245

        Thread.sleep(1000);
        watch.split();
        System.out.println("從開(kāi)始到第二個(gè)切入點(diǎn)運(yùn)行時(shí)間:" + watch.getSplitTime());

        watch.reset(); //重置后必須使用start方法
        watch.start();
        Thread.sleep(1000);
        System.out.println("重新開(kāi)始后到當(dāng)前運(yùn)行時(shí)間是:" + watch.getTime()); //1000

        watch.suspend(); //暫停
        Thread.sleep(6000); //模擬暫停6秒鐘

        watch.resume(); //上面suspend,這里要想重新統(tǒng)計(jì),需要恢復(fù)一下
        System.out.println("恢復(fù)后執(zhí)行的時(shí)間是:" + watch.getTime()); //1000  注意此時(shí)這個(gè)值還是1000

        watch.stop();
        System.out.println("花費(fèi)的時(shí)間》》" + watch.getTime() + "ms"); //1002ms
        System.out.println("花費(fèi)的時(shí)間》》" + watch.getTime(TimeUnit.SECONDS) + "s"); //1s 可以直接轉(zhuǎn)成s

    }

打印結(jié)果:

統(tǒng)計(jì)從開(kāi)始到現(xiàn)在運(yùn)行時(shí)間:1007ms
從start到此刻為止的時(shí)間:2008
從開(kāi)始到第一個(gè)切入點(diǎn)運(yùn)行時(shí)間:2008
從開(kāi)始到第二個(gè)切入點(diǎn)運(yùn)行時(shí)間:3009
重新開(kāi)始后到當(dāng)前運(yùn)行時(shí)間是:1000
恢復(fù)后執(zhí)行的時(shí)間是:1000
花費(fèi)的時(shí)間》》1001ms
花費(fèi)的時(shí)間》》1s

如上就是StopWatch的基本使用方法,足以見(jiàn)到了它的強(qiáng)大吧,當(dāng)然使用起來(lái)復(fù)雜度也是提升了些的。

核心原理解釋

原理相對(duì)簡(jiǎn)單,簡(jiǎn)單看看源碼便知:

// @since 2.0
public class StopWatch {
    // @since 3.5  這個(gè)靜態(tài)方法出現(xiàn)得稍微晚點(diǎn)哦~
    public static StopWatch createStarted() {
        final StopWatch sw = new StopWatch();
        sw.start();
        return sw;
    }

    // 這些成員變量是實(shí)現(xiàn)的核心~~~~~~~~~~~~~~
    private State runningState = State.UNSTARTED;
    private SplitState splitState = SplitState.UNSPLIT;
    private long startTime;
    // 思考:為何有了nonaTime這里還得記錄一個(gè)Millis Time呢???
    // 因?yàn)閚anoTime只能拿來(lái)計(jì)算差值(耗時(shí)) 但是getStartTime()這個(gè)老API還得靠MillsTime~~~
    private long startTimeMillis;
    private long stopTime;
    
    // 可見(jiàn):start方法可不是能夠多次調(diào)用的哦~~和狀態(tài)是有關(guān)的
    public void start() {
        if (this.runningState == State.STOPPED) {
            throw new IllegalStateException("Stopwatch must be reset before being restarted. ");
        }
        if (this.runningState != State.UNSTARTED) {
            throw new IllegalStateException("Stopwatch already started. ");
        }
        this.startTime = System.nanoTime();
        this.startTimeMillis = System.currentTimeMillis();
        this.runningState = State.RUNNING;
    }

    // 停表時(shí),最重要的是記錄下了stopTime 的值~~~然后標(biāo)記狀態(tài)
    public void stop() {
        if (this.runningState != State.RUNNING && this.runningState != State.SUSPENDED) {
            throw new IllegalStateException("Stopwatch is not running. ");
        }
        if (this.runningState == State.RUNNING) {
            this.stopTime = System.nanoTime();
        }
        this.runningState = State.STOPPED;
    }

    // 狀態(tài)變?yōu)榉情_(kāi)始狀態(tài)...
    public void reset() {
        this.runningState = State.UNSTARTED;
        this.splitState = SplitState.UNSPLIT;
    }

    // 暫停:stopTime 也給了一個(gè)值
    public void suspend() {
        if (this.runningState != State.RUNNING) {
            throw new IllegalStateException("Stopwatch must be running to suspend. ");
        }
        this.stopTime = System.nanoTime();
        this.runningState = State.SUSPENDED;
    }

    // 這兩個(gè)方法是獲取差值的
    public long getTime() {
        return getNanoTime() / NANO_2_MILLIS;
    }
    // @since 3.5
    public long getTime(final TimeUnit timeUnit) {
        return timeUnit.convert(getNanoTime(), TimeUnit.NANOSECONDS);
    }

    // @since 2.4 老API  這叫獲取啟動(dòng)的時(shí)間(啥時(shí)候啟動(dòng)的)
    public long getStartTime() {
        if (this.runningState == State.UNSTARTED) {
            throw new IllegalStateException("Stopwatch has not been started");
        }
        // System.nanoTime is for elapsed time
        return this.startTimeMillis;
    }
}

可以看到原理是很簡(jiǎn)單的,無(wú)非就是包裝了暫停、回復(fù)、split等功能嘛

使用細(xì)節(jié)

==getTimegetSplitTime有啥區(qū)別呢?==
為了說(shuō)明問(wèn)題,此處我們看看getNanoTime()getSplitNanoTime()亦可:

    public long getNanoTime() {
        if (this.runningState == State.STOPPED || this.runningState == State.SUSPENDED) {
            return this.stopTime - this.startTime;
        } else if (this.runningState == State.UNSTARTED) {
            return 0;
        } else if (this.runningState == State.RUNNING) {
            return System.nanoTime() - this.startTime;
        }
        throw new RuntimeException("Illegal running state has occurred.");
    }

     public long getSplitNanoTime() {
        if (this.splitState != SplitState.SPLIT) {
            throw new IllegalStateException("Stopwatch must be split to get the split time. ");
        }
        return this.stopTime - this.startTime;
    }

我們發(fā)現(xiàn):

調(diào)用getSplit...相關(guān)方法前,必須先調(diào)用Split方法

spilit()方法源碼如下:

    public void split() {
        if (this.runningState != State.RUNNING) {
            throw new IllegalStateException("Stopwatch is not running. ");
        }
        this.stopTime = System.nanoTime();
        this.splitState = SplitState.SPLIT;
    }

在調(diào)用split方法后,watch的狀態(tài)改為了SPLIT。且,且,且stopTime 設(shè)置為了當(dāng)前時(shí)間。因此此處我們的stopTime停止了,這個(gè)時(shí)候調(diào)用getSplitNanoTime(),返回的是start到split那時(shí)的時(shí)間差值。因此用此方法可以插入先停止stopTime()(有點(diǎn)插隊(duì)的趕腳),最后再輸出(先插好隊(duì),最后在輸出)~

getTime()就是拿當(dāng)前的時(shí)間戳,減去startTime,一般不涉及到stopTime的值,因此splitTime處理計(jì)算時(shí)間顯然更加的靈活,但是,一般我們使用getTime()就足夠了

Spring的StopWatch

Spring提供的這個(gè)任務(wù)監(jiān)視器,我還是蠻喜歡使用的,因?yàn)橐粋€(gè)它能夠幫我同事監(jiān)控多個(gè)任務(wù),使用起來(lái)也很方便。先看一個(gè)簡(jiǎn)單的使用案例:

注意:一個(gè)監(jiān)視器能夠記錄多個(gè)任務(wù)的執(zhí)行時(shí)間這個(gè)特點(diǎn)非常重要哦~
比如:我們可以記錄多段代碼耗時(shí)時(shí)間,然后一次性打印~
    public static void main(String[] args) throws Exception {
        // 強(qiáng)烈每一個(gè)秒表都給一個(gè)id,這樣查看日志起來(lái)能夠更加的精確
        // 至于Id 我覺(jué)得給UUID是可行的~
        StopWatch sw = new StopWatch(UUID.randomUUID().toString());

        sw.start("起床");
        Thread.sleep(1000);
        System.out.println("當(dāng)前任務(wù)名稱:" + sw.currentTaskName());
        sw.stop();

        sw.start("洗漱");
        Thread.sleep(2000);
        System.out.println("當(dāng)前任務(wù)名稱:" + sw.currentTaskName());
        sw.stop();

        sw.start("鎖門(mén)");
        Thread.sleep(500);
        System.out.println("當(dāng)前任務(wù)名稱:" + sw.currentTaskName());
        sw.stop();

        System.out.println(sw.prettyPrint()); // 這個(gè)方法打印在我們記錄日志時(shí)是非常友好的  還有百分比的分析哦
        System.out.println(sw.shortSummary());
        System.out.println(sw.currentTaskName()); // stop后它的值為null


        // 最后一個(gè)任務(wù)的相關(guān)信息
        System.out.println(sw.getLastTaskName());
        System.out.println(sw.getLastTaskInfo());

        // 任務(wù)總的耗時(shí)  如果你想獲取到每個(gè)任務(wù)詳情(包括它的任務(wù)名、耗時(shí)等等)可使用
        System.out.println("所有任務(wù)總耗時(shí):" + sw.getTotalTimeMillis());
        System.out.println("任務(wù)總數(shù):" + sw.getTaskCount());
        System.out.println("所有任務(wù)詳情:" + sw.getTaskInfo()); // 拿到所有的任務(wù)
    }

打印:

當(dāng)前任務(wù)名稱:起床
當(dāng)前任務(wù)名稱:洗漱
當(dāng)前任務(wù)名稱:鎖門(mén)
StopWatch "d6ba9412-d551-4ba7-8b0e-1b7ccb42855d": running time (millis) = 3504
-----------------------------------------
ms     %     Task name
-----------------------------------------
01001  029%  起床
02000  057%  洗漱
00503  014%  鎖門(mén)

StopWatch "d6ba9412-d551-4ba7-8b0e-1b7ccb42855d": running time (millis) = 3504
null
鎖門(mén)
org.springframework.util.StopWatch$TaskInfo@2d554825
所有任務(wù)總耗時(shí):3504
任務(wù)總數(shù):3
所有任務(wù)詳情:[Lorg.springframework.util.StopWatch$TaskInfo;@68837a77

我個(gè)人偏愛(ài)使用Spring提供的這個(gè)監(jiān)視器,是因?yàn)樗峁┑?b>prettyPrint()打印在日志里進(jìn)行分析可以非常的直觀,并且我覺(jué)得提供的多任務(wù)支持也更加實(shí)用一點(diǎn),當(dāng)然僅僅個(gè)人偏好而已~

最后

很多時(shí)候,寫(xiě)代碼也是一種藝術(shù),而借助這種實(shí)用工具我就覺(jué)得藝術(shù)感更強(qiáng)些。希望我們能有追求更加美好事物的心,這點(diǎn)對(duì)于接納新知識(shí)特別重要。此處推薦這個(gè)監(jiān)視器來(lái)代替之前的的使用,能讓小伙伴們更加靈活的分析你的代碼~

知識(shí)交流
若文章格式混亂,可點(diǎn)擊:原文鏈接-原文鏈接-原文鏈接-原文鏈接-原文鏈接

==The last:如果覺(jué)得本文對(duì)你有幫助,不妨點(diǎn)個(gè)贊唄。當(dāng)然分享到你的朋友圈讓更多小伙伴看到也是被作者本人許可的~==

**若對(duì)技術(shù)內(nèi)容感興趣可以加入wx群交流:Java高工、架構(gòu)師3群
若群二維碼失效,請(qǐng)加wx號(hào):fsx641385712(或者掃描下方wx二維碼)。并且備注:"java入群" 字樣,會(huì)手動(dòng)邀請(qǐng)入群**

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/75636.html

相關(guān)文章

  • 百度java學(xué)習(xí)筆記

    摘要:一般在存當(dāng)前含有當(dāng)前時(shí)間的實(shí)體時(shí),只需要配置好數(shù)據(jù)庫(kù)的存儲(chǔ)字段即可?;敬a部分循環(huán)的寫(xiě)法 這幾天初步了解了百度云的后臺(tái)架構(gòu)部分,當(dāng)然了,自己了解的僅限于后臺(tái)java相關(guān)的部分,先說(shuō)一下客戶端這邊使用的技術(shù):1、spring boot : 與前端進(jìn)行直接交互的服務(wù)是用spring來(lái)實(shí)現(xiàn)的(后臺(tái)服務(wù)還需要調(diào)用其他的基礎(chǔ)服務(wù),如redis 數(shù)據(jù)庫(kù)服務(wù) 訂單服務(wù) cdn服務(wù) openstac...

    codeGoogle 評(píng)論0 收藏0
  • SpringBoot ActiveMQ 整合使用

    摘要:介紹它是出品,最流行的,能力強(qiáng)勁的開(kāi)源消息總線。是一個(gè)完全支持和規(guī)范的實(shí)現(xiàn),盡管規(guī)范出臺(tái)已經(jīng)是很久的事情了,但是在當(dāng)今的應(yīng)用中間仍然扮演著特殊的地位。相關(guān)文章整合使用整合使用關(guān)注我轉(zhuǎn)載請(qǐng)務(wù)必注明原創(chuàng)地址為安裝同之前一樣,直接在里面玩吧。 showImg(https://segmentfault.com/img/remote/1460000012996066?w=1920&h=1281)...

    gaara 評(píng)論0 收藏0
  • 徹底征服 Spring AOP 之 實(shí)戰(zhàn)篇

    摘要:接上一小節(jié)徹底征服之理論篇實(shí)戰(zhàn)看了上面這么多的理論知識(shí)不知道大家有沒(méi)有覺(jué)得枯燥哈不過(guò)不要急俗話說(shuō)理論是實(shí)踐的基礎(chǔ)對(duì)有了基本的理論認(rèn)識(shí)后我們來(lái)看一下下面幾個(gè)具體的例子吧下面的幾個(gè)例子是我在工作中所遇見(jiàn)的比較常用的的使用場(chǎng)景我精簡(jiǎn)了很多有干擾我 接上一小節(jié)徹底征服 Spring AOP 之 理論篇 Spring AOP 實(shí)戰(zhàn) 看了上面這么多的理論知識(shí), 不知道大家有沒(méi)有覺(jué)得枯燥哈. 不過(guò)不...

    CNZPH 評(píng)論0 收藏0
  • SpringBoot RocketMQ 整合使用監(jiān)控

    摘要:前提通過(guò)前面兩篇文章可以簡(jiǎn)單的了解和安裝,今天就將和整合起來(lái)使用。然后我運(yùn)行之前的整合項(xiàng)目,查看監(jiān)控信息如下總結(jié)整篇文章講述了與整合和監(jiān)控平臺(tái)的搭建。 showImg(https://segmentfault.com/img/remote/1460000013232432?w=1920&h=1277); 前提 通過(guò)前面兩篇文章可以簡(jiǎn)單的了解 RocketMQ 和 安裝 RocketMQ...

    Jacendfeng 評(píng)論0 收藏0
  • 漲姿勢(shì):Spring Boot 2.x 啟動(dòng)全過(guò)程源碼分析

    摘要:參考創(chuàng)建所有運(yùn)行監(jiān)聽(tīng)器并發(fā)布應(yīng)用啟動(dòng)事件來(lái)看下創(chuàng)建運(yùn)行監(jiān)聽(tīng)器相關(guān)的源碼創(chuàng)建邏輯和之前實(shí)例化初始化器和監(jiān)聽(tīng)器的一樣,一樣調(diào)用的是方法來(lái)獲取配置的監(jiān)聽(tīng)器名稱并實(shí)例化所有的類。 上篇《Spring Boot 2.x 啟動(dòng)全過(guò)程源碼分析(一)入口類剖析》我們分析了 Spring Boot 入口類 SpringApplication 的源碼,并知道了其構(gòu)造原理,這篇我們繼續(xù)往下面分析其核心 ru...

    suemi 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<