java - Apache Lang3 StopWatch.split()的意义是什么?

标签 java apache-commons apache-commons-lang3

我目前正在评估Apache StopWatch和Guava的Stopwatch之间的实现,前者中的拆分功能引起了我的兴趣,但我一直在努力了解它的确切功能和值(value)。
根据StopWatch的文档:https://commons.apache.org/proper/commons-lang/javadocs/api-3.9/org/apache/commons/lang3/time/StopWatch.html

split() the watch to get the time whilst the watch continues in the background. unsplit() will remove the effect of the split. At this point, these three options are available again.


而且我发现了一些示例,例如this,由于拆分似乎只是累积性的,所以提供的很少。页面上说该方法用于“拆分时间”,我根据该方法认为这是最多的,但是页面未提及这实际上意味着什么。甚至看起来这个例子是完全错误的,因为文档建议您应该在再次使用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秒,但似乎这两种方法都输出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()调用没有区别...我也尝试过此操作,并且对我来说,时间仍然是一样的。
我在这里错过了什么吗?还是我对这应该做的一切的解释都是错的?

最佳答案

这是source code getSplitTime() (内部调用此其他函数):

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()时,该变量将被覆盖。
尽管共享相同的变量可能看起来有些奇怪,但这确实是有道理的,因为splittedTime StopWatch 不应大于总经过时间。因此,这是一个有关 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()函数的简单性(这也几乎不能回答OP的问题)。它负责:
  • 检查 StopWatch 是否正在运行。
  • 标记一个新的stopTime
  • splitState设置为 SPLIT
  •                                       TLDR lol
    
    在停止getSplitTime()之前调用StopWatch应该会向您显示所需的值:
  • 尚无法更新。
  • 现在,返回值将与最后一个stopTime stop() 之间经过的时间匹配。

  • 一些示例:(是的,在星期六晚上进行编辑,因为我需要社交生活)
    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
    
    还有最后一个。您知道,这是用split()模拟时间的,只是为了好玩。我很无聊,我真的进口了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
    

    请注意,在停止的startTime上调用sleeps不会引发任何异常,因为该方法仅在getSplitTime()时才会检查Watch
    混淆可能是由以下两个事实引起的:
  • 该代码允许您使用splitState而不考虑SPLIT,从而使最后一个stop()毫无用处。徒劳的,我喜欢这个词。必须以某种方式将其包括在我的答案中。 Futileeee
  • 它还允许您在已停止的 watch 上检查SplitState(如果它仍处于split()状态),此时它实际上只会返回上一个splittedTime和停止时间之间的总经过时间。 (小骗子)

  • 在这种情况下,秒表同时停止并拆分,当在SPLIT之后调用start()getTime()时,它们始终显示相同的值。

    [个人和主观意见]
    假设您有一个getSplitTime()类,该类具有不同的变量来检查经过的时间。您还希望每60秒输出一次操作的总经过时间。在此示例中,stop() Counters 类的实例,该类拥有两个counters变量:Counterslong,它们将在特定时间间隔(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;
    }
    
    fileTime类可以实现sendTimeCounters函数,以清理上面的代码。它还可以管理reset()变量。这只是简化其行为的一个示例。
    对于此用例,在中,您需要持久地测量不同的操作,我认为这种方式更易于使用,并且似乎具有相似的性能,因为 showTimes() 在内部完全相同。但是,这只是我的操作方式:)。
    我将以光荣而徒劳的方式接受对此观点的否决。
    为了表达对elapsedStatsTimer的敬意,我想以一分钟的沉默结束,这可能是有史以来最不相关的方法之一。
    [/个人和主观意见]

    刚刚注意到StopWatch部分实际上大于上一部分:_)

    关于java - Apache Lang3 StopWatch.split()的意义是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62804809/

    相关文章:

    java - 单选按钮上的 Action 监听器

    Java servlet java.lang.UnsupportedClassVersionError

    java - 如何将此 JSON 转换为 JAVA android 中的对象?

    Java : Unable to delete files using FileUtils. 安静地删除,强制删除,FileDeleteStrategy.FORCE.delete;

    java - 如何在使用 Apache 的 Tailer 包监视文件时获取文件名?

    java - 我如何将 boolean 值传递给新对象?

    java - 与 apache commons-vfs2 的连接过多

    java - 计时方法持续时间: always showing zero seconds?

    java - Apache Commons Lang : Can the "incompatibilities" between 'lang' and 'lang3' cause different runtime results?

    java - Maven 和 apache utils 的编译错误不明确