繁体   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