spring-framework的StopWatch类详解,每个方法带有具体的例子
简介:
org.apache.commons.lang3.time.StopWatch 是 Apache Commons Lang 库中的一个工具类,用于测量代码执行时间。这个类提供了一系列便捷的方法,可以帮助我们轻松地对 Java 代码中的耗时操作进行计时。
StopWatch 类的应用场景:
StopWatch 类可以在许多场景下派上用场,例如:
- 性能调优和基准测试:
- 使用 StopWatch 可以方便地测量代码段的执行时间,从而找到可能存在性能问题的代码。
- 运行时监控:
- 在某些关键任务执行过程中,可以使用 StopWatch 记录其执行时间,以便在后期进行性能分析。
- 操作计时:
- 在需要精确计时的操作中,例如限制某个任务的执行时间,可以使用 StopWatch 进行计时。
StopWatch 类提供了以下一些主要方法:
start():
描述:启动计时器。如果计时器已经启动,则会抛出 IllegalStateException。
使用场景:开始测量代码段的执行时间。
源码:
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;
}
示例:
StopWatch stopWatch = new StopWatch();
stopWatch.start(); // 启动计时器
stop():
描述:停止计时器。如果计时器尚未启动,则会抛出 IllegalStateException。
使用场景:结束测量代码段的执行时间。
源码:
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;
}
示例:
StopWatch stopWatch = new StopWatch();
stopWatch.start(); // 启动计时器
// ... 执行一段代码 ...
stopWatch.stop(); // 停止计时器
reset():
描述:重置计时器。将计时器状态恢复到初始状态。
使用场景:在连续测量多个代码段时,可以在每次测量之前重置计时器。
源码:
public void reset() {
this.runningState = State.UNSTARTED;
this.splitState = SplitState.UNSPLIT;
}
示例:
StopWatch stopWatch = new StopWatch();
stopWatch.start(); // 启动计时器
// ... 执行一段代码 ...
stopWatch.stop(); // 停止计时器
stopWatch.reset(); // 重置计时器
split():
描述:将计时器分割为两部分,此时可以获取分割点的时间。调用此方法后,计时器将继续运行。
使用场景:在测量一个长时间执行的任务时,可以使用此方法分割多个子任务的执行时间。
源码:
public void split() {
if (this.runningState != State.RUNNING) {
throw new IllegalStateException("Stopwatch is not running. ");
}
this.stopTime = System.nanoTime();
this.splitState = SplitState.SPLIT;
}
示例:
StopWatch stopWatch = new StopWatch();
stopWatch.start(); // 启动计时器
// ... 执行子任务1 ...
stopWatch.split(); // 分割计时器
// ... 执行子任务2 ...
stopWatch.stop(); // 停止计时器
unsplit():
描述:取消分割,恢复计时器到分割前的状态。
使用场景:在使用 split() 方法分割计时器后,如果需要恢复到分割前的状态,可以调用此方法。
源码:
public void unsplit() {
if (this.splitState != SplitState.SPLIT) {
throw new IllegalStateException("Stopwatch has not been split. ");
}
this.splitState = SplitState.UNSPLIT;
}
示例:
StopWatch stopWatch = new StopWatch();
stopWatch.start(); // 启动计时器
// ... 执行子任务1 ...
stopWatch.split(); // 分割计时器
// ... 执行子任务2 ...
stopWatch.unsplit(); // 取消分割
// ... 继续执行其他任务 ...
stopWatch.stop(); // 停止计时器
getTime():
描述:获取计时器记录的总时间,单位为毫秒。如果计时器正在运行,则返回当前已记录的时间;如果计时器已停止,则返回停止时的时间。
使用场景:在计时器停止后,获取代码段执行的总时间。
源码:
public long getTime() {
return getNanoTime() / NANO_2_MILLIS;
}
示例:
StopWatch stopWatch = new StopWatch();
stopWatch.start(); // 启动计时器
// ... 执行一段代码 ...
stopWatch.stop(); // 停止计时器
long elapsedTime = stopWatch.getTime(); // 获取已记录的时间
System.out.println("执行时间:" + elapsedTime + " 毫秒");
getStartTime():
描述:获取计时器开始时间,以毫秒为单位。返回值是自 epoch(1970-01-01T00:00:00Z)起的毫秒数。
使用场景:在需要获取计时器启动时的时间戳时使用。
源码:
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;
}
示例:
StopWatch stopWatch = new StopWatch();
stopWatch.start(); // 启动计时器
long startTime = stopWatch.getStartTime(); // 获取计时器启动时间
System.out.println("计时器启动时间:" + new Date(startTime));
toString():
描述:将计时器的状态以字符串形式返回。输出的格式为 "HH:mm:ss.SSS",表示经过的小时、分钟、秒和毫秒。
使用场景:当需要将计时器的状态以人类可读的形式输出时使用。
源码:
@Override
public String toString() {
final String msgStr = Objects.toString(message, StringUtils.EMPTY);
final String formattedTime = formatTime();
return msgStr.isEmpty() ? formattedTime : msgStr + StringUtils.SPACE + formattedTime;
}
示例:
StopWatch stopWatch = new StopWatch();
stopWatch.start(); // 启动计时器
// ... 执行一段代码 ...
stopWatch.stop(); // 停止计时器
System.out.println("执行时间:" + stopWatch.toString());
isStarted():
描述:检查计时器是否已启动。如果计时器已启动且尚未停止,则返回 true;否则返回 false。
使用场景:在需要检查计时器是否处于运行状态时使用。
源码:
public boolean isStarted() {
return runningState.isStarted();
}
示例:
StopWatch stopWatch = new StopWatch();
System.out.println("计时器是否已启动:" + stopWatch.isStarted()); // 输出:false
stopWatch.start(); // 启动计时器
System.out.println("计时器是否已启动:" + stopWatch.isStarted()); // 输出:true
isStopped():
描述:检查计时器是否已停止。如果计时器已停止,则返回 true;否则返回 false。
使用场景:在需要检查计时器是否处于停止状态时使用。
源码:
public boolean isStopped() {
return runningState.isStopped();
}
示例:
StopWatch stopWatch = new StopWatch();
System.out.println("计时器是否已停止:" + stopWatch.isStopped()); // 输出:true
stopWatch.start(); // 启动计时器
System.out.println("计时器是否已停止:" + stopWatch.isStopped()); // 输出:false
stopWatch.stop(); // 停止计时器
System.out.println("计时器是否已停止:" + stopWatch.isStopped()); // 输出:true
示例代码:
以下是一个使用 StopWatch 测量代码执行时间的简单示例:
import org.apache.commons.lang3.time.StopWatch;
public class StopWatchExample {
public static void main(String[] args) throws InterruptedException {
// 创建一个 StopWatch 实例
StopWatch stopWatch = new StopWatch();
// 启动计时器
stopWatch.start();
// 执行一段耗时操作
Thread.sleep(2000);
// 停止计时器
stopWatch.stop();
// 输出执行时间
System.out.println("耗时:" + stopWatch.getTime() + " 毫秒");
}
}
在这个示例中,我们创建了一个 StopWatch 实例,然后使用 start() 方法开始计时。接下来,我们执行一个简单的耗时操作(暂停线程 2 秒),最后使用 stop() 方法停止计时器。最后,我们输出耗时,可以看到结果大约是 2000 毫秒。
以下是一个使用 StopWatch 类的复杂示例,该示例演示了如何使用 split() 和 unsplit() 方法来分割和取消分割计时器,以及如何使用 getTime() 方法获取分割点的时间:
import org.apache.commons.lang3.time.StopWatch;
public class ComplexStopWatchExample {
public static void main(String[] args) throws InterruptedException {
StopWatch stopWatch = new StopWatch();
stopWatch.start(); // 启动计时器
// 执行子任务1,耗时1000毫秒
Thread.sleep(1000);
stopWatch.split(); // 分割计时器
System.out.println("子任务1耗时:" + stopWatch.getTime() + " 毫秒");
// 执行子任务2,耗时2000毫秒
Thread.sleep(2000);
stopWatch.split(); // 分割计时器
System.out.println("子任务2耗时:" + (stopWatch.getTime() - stopWatch.getSplitTime()) + " 毫秒");
// 取消分割,继续执行其他任务
stopWatch.unsplit();
// 执行子任务3,耗时1500毫秒
Thread.sleep(1500);
stopWatch.stop(); // 停止计时器
System.out.println("总耗时:" + stopWatch.getTime() + " 毫秒");
}
}
在这个示例中,我们执行了三个子任务,并使用 split() 方法在每个子任务之间进行分割。通过调用 getTime() 方法并减去之前的分割时间,我们可以得到每个子任务的执行时间。通过调用 unsplit() 方法,我们可以取消分割并继续计时。最后,我们停止计时器并输出总耗时。