簡體   English   中英

Apache Lang3 StopWatch.split() 的意義何在?

[英]What is the point of Apache Lang3 StopWatch.split()?

我目前正在評估 Apache 秒表和番石榴的秒表之間的實現,前者的拆分功能讓我很感興趣,但我很難理解它到底做了什么,以及它有什么價值。

根據秒表的文檔: https://commons.apache.org/proper/commons-lang/javadocs/api-3.9/org/apache/commons/lang3/time/StopWatch.ZD2535FDC70AD5FC27988E

split() 手表在后台繼續運行時獲取時間。 unsplit() 將刪除拆分的效果。 此時,這三個選項再次可用。

我發現了一些例子,比如this ,它提供的很少,因為它看起來 split 只是累積的。 該頁面說該方法用於“分割時間”,我根據該方法得出了同樣多的結論,但該頁面沒有提及這實際上意味着什么。 甚至看起來這個例子是完全錯誤的,因為文檔建議你應該在再次unsplit之前取消split

我最初認為它適用於以下用例:

StopWatch stopwatch = StopWatch.createStarted();
do something for 5 seconds
stopwatch.split();
do something for 10 seconds
stopwatch.stop();
System.out.println(stopwatch.getTime());
System.out.println(stopwatch.getSplitTime());

我認為秒表總時間讀作 15 秒,秒表分割時間讀作 10 或 5 秒,但似乎這兩種方法 output 都是 15 秒。

接下來,我認為拆分值可能是您可以采用的增量,然后從總計時器中刪除,例如:

StopWatch stopwatch = StopWatch.createStarted();
do something for 5 seconds
stopwatch.split();
do something for 10 seconds
stopwatch.unsplit();
stopwatch.stop();
System.out.println(stopwatch.getTime());
// System.out.println(stopwatch.getSplitTime()); errors because of unsplit

我的想法是拆分時間為 10 秒,當從主計時器未拆分時,主計時器將讀取為 5 秒......但這似乎與suspend()調用沒有什么不同......我也試過這個,而且時間對我來說還是一樣的。

我在這里遺漏了什么,還是我對這應該做的事情的解釋都是錯誤的?

這是getSplitTime()源代碼它在內部調用另一個 function ):

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;
}

所以它會返回stopTime-startTime 當心stopTime 是騙子讓你困惑。

這是stop()的代碼:

public void stop() {
  if (this.runningState != State.RUNNING && this.runningState != State.SUSPENDED) {
    throw new IllegalStateException("Stopwatch is not running. ");
  }
  if (this.runningState == State.RUNNING) 
  {
    //is this the same stopTime getSplitTime uses? yep, it is
     this.stopTime = System.nanoTime(); 
  }
  this.runningState = State.STOPPED;
}

那會發生什么?

調用stop()會更新stopTime變量並使秒表“忘記”上次拆分的時間。

split()stop()都修改了相同的變量stopTime ,當您在進程結束時調用stop()時,該變量會被覆蓋。

盡管共享同一個變量可能看起來很奇怪,但它確實很有意義,因為StopWatchsplittedTime永遠不應大於總經過時間。 所以這是一個關於StopWatch中執行的功能順序的游戲。

這是split()的代碼,以便看到這兩種方法都使用stopTime

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

這就是為什么這個可愛的 Apache 騙子會在 splittedTime 上顯示 15 秒:因為stop()更新了stopTime變量getSplitTime()將用於返回其值。 第一個代碼片段

請注意split() function 的簡單性(這也幾乎沒有回答 OP 的問題)。 它負責:

  1. 檢查StopWatch是否正在運行。
  2. 標記一個新的stopTime
  3. splitState設置為SPLIT

                                      TLDR lol

在停止StopWatch之前調用getSplitTime()應該會顯示所需的值

  1. stopTime不會被stop()更新。
  2. 返回值現在將匹配上次split()startTime之間經過的時間。

一些例子:(是的,周六晚上編輯,因為我需要社交生活

StopWatch stopwatch = StopWatch.createStarted();
do something for 5 seconds
stopwatch.split(); //stopTime is updated [by split()]
System.out.println(stopwatch.getSplitTime()); // will show 5 seconds
do something for 10 seconds
System.out.println(stopwatch.getSplitTime()); // will also show 5 seconds
stopwatch.stop(); //stopTime is updated again [by stop()]
System.out.println(stopwatch.getTime()); // 15s
System.out.println(stopwatch.getSplitTime()); // 15s

另一個:

StopWatch stopwatch = StopWatch.createStarted();
do something for 5 seconds
stopwatch.split(); 
System.out.println(stopwatch.getSplitTime()); // 5s
do something for 10 seconds
stopwatch.split(); 
System.out.println(stopwatch.getSplitTime()); // 15s
do something for 1 second
stopwatch.stop();
System.out.println(stopwatch.getTime()); // 16s

最后一個。 sleeps來嘲笑時間,只是為了好玩,你知道的。 我太無聊了,我真的進口了 apache jar 以便在本地進行測試

StopWatch stopwatch = StopWatch.createStarted();
Thread.sleep(5000);
stopwatch.split(); 
System.out.println(stopwatch.getSplitTime()); // 5s
Thread.sleep(10000);
stopwatch.split(); 
System.out.println(stopwatch.getSplitTime()); // 15s

stopwatch.reset();  // allows the stopWatch to be started again
stopwatch.start();  // updates startTime

Thread.sleep(2000);
stopwatch.split(); 
System.out.println(stopwatch.getSplitTime()); // 2s
Thread.sleep(1000);
stopwatch.stop();
System.out.println(stopwatch.getTime());      // 3s
System.out.println(stopwatch.getSplitTime()); // 3s
//it was so fun putting the sleeps

請注意,在停止的Watch上調用getSplitTime()不會引發任何異常,因為該方法只會檢查splitState是否為SPLIT

混淆可能是由以下兩個事實引起的:

  1. 該代碼允許您stop()而不管SplitState ,使您的最后一個split()在您不知道的情況下徒勞無功。 徒勞的,我喜歡這個詞。 不得不以某種方式將其包含在我的答案中。 徒勞的
  2. 它還允許您在停止的手表上檢查splittedTime (如果它仍處於SPLIT狀態),它實際上只會返回上次start()和停止時間之間的總經過時間。 (小騙子)

在這種情況下,秒表同時停止和拆分, getTime()getSplitTime()stop()之后調用時將始終顯示相同的值。


[個人和主觀意見]

假設您有一個帶有不同變量的Counters class 來檢查經過的時間。 您還希望 output 每次操作的總經過時間,每 60 秒。 在此示例中, countersCounters class 的一個實例,它擁有兩個long變量: fileTimesendTime ,它們將在特定時間間隔 ( 60s ) 內累積每個操作中的經過時間。 這只是一個假設每次迭代時間少於 1000 毫秒的示例(因此它總是顯示經過時間為 60 秒):

long statsTimer = System.currentTimeMillis();
while (mustWork)
{
    long elapsedStatsTimer = System.currentTimeMillis()-statsTimer; //hits 60185 
   
    if (elapsedStatsTimer  > 60000)
    {
       //counters.showTimes()
       System.out.println("Showing elapsed times for the last "+
                            (elapsedStatsTimer/1000)+ " secs"); //(60185/1000) - 60 secs
       System.out.println("Files time: "+counters.fileTime+" ms"); //23695 ms
       System.out.println("Send time : "+counters.sendTime+" ms"); //36280 ms          
       long workTime = counters.sendTime+counters.fileTime;
       System.out.println("Work time : "+workTime+" ms"); //59975 ms
       System.out.println("Others    : "+(elapsedStatsTimer-workTime)+" ms"); //210 ms
       //counters.reset()
       counters.fileTime=0;
       counters.sendTime=0;
       statsTimer= System.currentTimeMillis();
     }
     
     long timer = System.currentTimeMillis();
     //do something with a file
     counters.fileTime+=System.currentTimeMillis-timer;
     timer = System.currentTimeMillis();
     //send a message
     counters.sendTime+=System.currentTimeMillis()-timer;
}

Counters class 可以實現reset()showTimes()函數,以清理上面的代碼。 它還可以管理elapsedStatsTimer變量。 這只是簡化其行為的示例。

對於這種需要持續測量不同操作的用例,我認為這種方式更易於使用並且似乎具有相似的性能,因為StopWatch在內部進行完全相同的事情。 但是,嘿,這只是我的做法:)。

我將以一種光榮和徒勞的方式接受對這一觀點的反對票。

我很想以一分鍾的沉默來結束unsplit() ,這可能是有史以來最不相關的方法之一。

[/個人主觀意見]


剛剛注意到TLDR部分實際上比上一部分大:_)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM