这是 getSplitTime() 的 source code(它在内部调用这个其他函数):
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() 时,该变量会被覆盖。
虽然共享同一个变量可能看起来很奇怪,但它确实很有意义,因为 StopWatch 的 splittedTime 永远不应大于总经过时间。所以这是一个关于 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() 将用于返回其值。 (第一个代码sn-p)
注意split() 函数的简单性(这也几乎没有回答 OP 的问题)。它负责:
- 检查
StopWatch 是否正在运行。
- 标记一个新的
stopTime。
- 将
splitState 设置为SPLIT。
TLDR lol
在停止 StopWatch 之前调用 getSplitTime() 应该会显示所需的值:
-
stopTime不会被stop()更新。
- 返回值现在将匹配最后一个
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.
混淆可能是由以下两个事实引起的:
- 无论
SplitState如何,该代码都允许您stop(),让您的最后一个split()在您不知情的情况下徒劳无功。徒劳的,我喜欢这个词。不得不以某种方式将其包含在我的答案中。 无用的人
- 它还允许您在停止的手表上检查
splittedTime(如果它仍处于SPLIT 状态),它实际上只会返回最后一个start() 和停止时间之间的总经过时间。 (小骗子)
在这种情况下,秒表同时停止和拆分,getTime() 和 getSplitTime() 在 stop() 之后调用时将始终显示相同的值。
[个人和主观意见]
假设您有一个 Counters 类,其中包含不同的变量来检查经过的时间。您还希望每 60 秒输出每个操作的总经过时间。在此示例中,counters 是 Counters 类的一个实例,该类拥有两个 long 变量:fileTime 和 sendTime,它们将在每个操作中累积经过的时间特定间隔(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 类可以实现reset() 和showTimes() 函数,以便清理上面的代码。它还可以管理elapsedStatsTimer 变量。这只是一个简化其行为的示例。
对于这种您需要持续测量不同操作的用例,我认为这种方式更容易使用并且似乎具有相似的性能,因为StopWatch 在内部制作完全相同的东西。但是,嘿,这只是我的方式:)。
我将以一种光荣而徒劳的方式接受对这一意见的反对票。
我很想以一分钟的沉默结束,以纪念unsplit(),这可能是有史以来最不相关的方法之一。
[/个人和主观意见]
刚刚注意到TLDR 部分实际上比上一个部分大 :_ )