网站做搜索引擎优化,网易企业邮箱官网登录,网络广告推广计划方案,蚌埠网站开发我们在日常开发中经常需要测试一些代码的执行时间#xff0c;但又不想使用向 JMH#xff08;Java Microbenchmark Harness#xff0c;Java 微基准测试套件#xff09;这么重的测试框架#xff0c;所以本文就汇总了一些 Java 中比较常用的执行时间统计方法#xff0c;总共… 我们在日常开发中经常需要测试一些代码的执行时间但又不想使用向 JMHJava Microbenchmark HarnessJava 微基准测试套件这么重的测试框架所以本文就汇总了一些 Java 中比较常用的执行时间统计方法总共包含以下 6 种如下图所示 方法一System.currentTimeMillis 此方法为 Java 内置的方法使用 System#currentTimeMillis 来统计执行的时间统计单位毫秒示例代码如下 public class TimeIntervalTest {public static void main(String[] args) throws InterruptedException {// 开始时间long stime System.currentTimeMillis();// 执行时间1sThread.sleep(1000);// 结束时间long etime System.currentTimeMillis();// 计算执行时间System.out.printf(执行时长%d 毫秒., (etime - stime));}
}以上程序的执行结果为 执行时长1000 毫秒. 方法二System.nanoTime 此方法为 Java 内置的方法使用 System#nanoTime 来统计执行时间统计单位纳秒它的执行方法和 System#currentTimeMillis 类似示例代码如下 public class TimeIntervalTest {public static void main(String[] args) throws InterruptedException {// 开始时间long stime System.nanoTime();// 执行时间1sThread.sleep(1000);// 结束时间long etime System.nanoTime();// 计算执行时间System.out.printf(执行时长%d 纳秒., (etime - stime));}
}以上程序的执行结果为 执行时长1000769200 纳秒. 小贴士1 毫秒 100 万纳秒。 方法三new Date 此方法也是 Java 的内置方法在开始执行前 new Date() 创建一个当前时间对象在执行结束之后 new Date() 一个当前执行时间然后再统计两个 Date 的时间间隔示例代码如下 import java.util.Date;public class TimeIntervalTest {public static void main(String[] args) throws InterruptedException {// 开始时间Date sdate new Date();// 执行时间1sThread.sleep(1000);// 结束时间Date edate new Date();// 统计执行时间毫秒System.out.printf(执行时长%d 毫秒. , (edate.getTime() - sdate.getTime())); }
}以上程序的执行结果为 执行时长1000 毫秒. 方法四Spring StopWatch 如果我们使用的是 Spring 或 Spring Boot 项目可以在项目中直接使用 StopWatch 对象来统计代码执行时间示例代码如下 StopWatch stopWatch new StopWatch();
// 开始时间
stopWatch.start();
// 执行时间1s
Thread.sleep(1000);
// 结束时间
stopWatch.stop();
// 统计执行时间秒
System.out.printf(执行时长%d 秒.%n, stopWatch.getTotalTimeSeconds()); // %n 为换行
// 统计执行时间毫秒
System.out.printf(执行时长%d 毫秒.%n, stopWatch.getTotalTimeMillis());
// 统计执行时间纳秒
System.out.printf(执行时长%d 纳秒.%n, stopWatch.getTotalTimeNanos());以上程序的执行结果为 执行时长0.9996313 秒. 执行时长999 毫秒. 执行时长999631300 纳秒. 小贴士Thread#sleep 方法的执行时间稍有偏差在 1s 左右都是正常的。 方法五commons-lang3 StopWatch 如果我们使用的是普通项目那我们可以用 Apache commons-lang3 中的 StopWatch 对象来实现时间统计首先先添加 commons-lang3 的依赖 !-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 --
dependencygroupIdorg.apache.commons/groupIdartifactIdcommons-lang3/artifactIdversion3.10/version
/dependency然后编写时间统计代码 import org.apache.commons.lang3.time.StopWatch;import java.util.concurrent.TimeUnit;public class TimeIntervalTest {public static void main(String[] args) throws InterruptedException {StopWatch stopWatch new StopWatch();// 开始时间stopWatch.start();// 执行时间1sThread.sleep(1000);// 结束时间stopWatch.stop();// 统计执行时间秒System.out.println(执行时长 stopWatch.getTime(TimeUnit.SECONDS) 秒.);// 统计执行时间毫秒System.out.println(执行时长 stopWatch.getTime(TimeUnit.MILLISECONDS) 毫秒.);// 统计执行时间纳秒System.out.println(执行时长 stopWatch.getTime(TimeUnit.NANOSECONDS) 纳秒.);}
}以上程序的执行结果为 执行时长1 秒. 执行时长1000 毫秒. 执行时长1000555100 纳秒. 方法六Guava Stopwatch 除了 Apache 的 commons-lang3 外还有一个常用的 Java 工具包那就是 Google 的 GuavaGuava 中也包含了 Stopwatch 统计类。首先先添加 Guava 的依赖 !-- https://mvnrepository.com/artifact/com.google.guava/guava --
dependencygroupIdcom.google.guava/groupIdartifactIdguava/artifactIdversion29.0-jre/version
/dependency然后编写时间统计代码 import com.google.common.base.Stopwatch;import java.util.concurrent.TimeUnit;public class TimeIntervalTest {public static void main(String[] args) throws InterruptedException {// 创建并启动计时器Stopwatch stopwatch Stopwatch.createStarted();// 执行时间1sThread.sleep(1000);// 停止计时器stopwatch.stop();// 执行时间单位秒System.out.printf(执行时长%d 秒. %n, stopwatch.elapsed().getSeconds()); // %n 为换行// 执行时间单位毫秒System.out.printf(执行时长%d 豪秒., stopwatch.elapsed(TimeUnit.MILLISECONDS));}
}以上程序的执行结果为 执行时长1 秒. 执行时长1000 豪秒. 原理分析 本文我们从 Spring 和 Google 的 Guava 源码来分析一下它们的 StopWatch 对象底层是如何实现的 1.Spring StopWatch 原理分析 在 Spring 中 StopWatch 的核心源码如下 package org.springframework.util;import java.text.NumberFormat;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.springframework.lang.Nullable;public class StopWatch {private final String id;private boolean keepTaskList;private final ListStopWatch.TaskInfo taskList;private long startTimeNanos;Nullableprivate String currentTaskName;Nullableprivate StopWatch.TaskInfo lastTaskInfo;private int taskCount;private long totalTimeNanos;public StopWatch() {this();}public StopWatch(String id) {this.keepTaskList true;this.taskList new LinkedList();this.id id;}public String getId() {return this.id;}public void setKeepTaskList(boolean keepTaskList) {this.keepTaskList keepTaskList;}public void start() throws IllegalStateException {this.start();}public void start(String taskName) throws IllegalStateException {if (this.currentTaskName ! null) {throw new IllegalStateException(Cant start StopWatch: its already running);} else {this.currentTaskName taskName;this.startTimeNanos System.nanoTime();}}public void stop() throws IllegalStateException {if (this.currentTaskName null) {throw new IllegalStateException(Cant stop StopWatch: its not running);} else {long lastTime System.nanoTime() - this.startTimeNanos;this.totalTimeNanos lastTime;this.lastTaskInfo new StopWatch.TaskInfo(this.currentTaskName, lastTime);if (this.keepTaskList) {this.taskList.add(this.lastTaskInfo);}this.taskCount;this.currentTaskName null;}}// .... 忽略其他代码
}从上述 start() 和 stop() 的源码中可以看出Spring 实现时间统计的本质还是使用了 Java 的内置方法 System.nanoTime() 来实现的。 2.Google Stopwatch 原理分析 Google Stopwatch 实现的核心源码如下 public final class Stopwatch {private final Ticker ticker;private boolean isRunning;private long elapsedNanos;private long startTick;CanIgnoreReturnValuepublic Stopwatch start() {Preconditions.checkState(!this.isRunning, This stopwatch is already running.);this.isRunning true;this.startTick this.ticker.read();return this;}CanIgnoreReturnValuepublic Stopwatch stop() {long tick this.ticker.read();Preconditions.checkState(this.isRunning, This stopwatch is already stopped.);this.isRunning false;this.elapsedNanos tick - this.startTick;return this;}// 忽略其他源码...
}从上述源码中可以看出 Stopwatch 对象中调用了 ticker 类来实现时间统计的那接下来我们进入 ticker 类的实现源码 public abstract class Ticker {private static final Ticker SYSTEM_TICKER new Ticker() {public long read() {return Platform.systemNanoTime();}};protected Ticker() {}public abstract long read();public static Ticker systemTicker() {return SYSTEM_TICKER;}
}
final class Platform {private static final Logger logger Logger.getLogger(Platform.class.getName());private static final PatternCompiler patternCompiler loadPatternCompiler();private Platform() {}static long systemNanoTime() {return System.nanoTime();}// 忽略其他源码...
}从上述源码可以看出 Google Stopwatch 实现时间统计的本质还是调用了 Java 内置的 System.nanoTime() 来实现的。 结论 对于所有框架的 StopWatch 来说其底层都是通过调用 Java 内置的 System.nanoTime() 得到两个时间开始时间和结束时间然后再通过结束时间减去开始时间来统计执行时间的。 总结 本文介绍了 6 种实现代码统计的方法其中 3 种是 Java 内置的方法 System.currentTimeMillis() System.nanoTime() new Date() 还介绍了 3 种常用框架 spring、commons-langs3、guava 的时间统计器 StopWatch。 在没有用到 spring、commons-langs3、guava 任意一种框架的情况下推荐使用 System.currentTimeMillis() 或 System.nanoTime() 来实现代码统计否则建议直接使用 StopWatch 对象来统计执行时间。 知识扩展—Stopwatch 让统计更方便 StopWatch 存在的意义是让代码统计更简单比如 Guava 中 StopWatch 使用示例如下 import com.google.common.base.Stopwatch;import java.util.concurrent.TimeUnit;public class TimeIntervalTest {public static void main(String[] args) throws InterruptedException {// 创建并启动计时器Stopwatch stopwatch Stopwatch.createStarted();// 执行时间1sThread.sleep(1000);// 停止计时器stopwatch.stop();// 执行统计System.out.printf(执行时长%d 毫秒. %n,stopwatch.elapsed(TimeUnit.MILLISECONDS));// 清空计时器stopwatch.reset();// 再次启动统计stopwatch.start();// 执行时间2sThread.sleep(2000);// 停止计时器stopwatch.stop();// 执行统计System.out.printf(执行时长%d 秒. %n,stopwatch.elapsed(TimeUnit.MILLISECONDS));}
}我们可以使用一个 Stopwatch 对象统计多段代码的执行时间也可以通过指定时间类型直接统计出对应的时间间隔比如我们可以指定时间的统计单位如秒、毫秒、纳秒等类型。 互动话题 你还知道哪些统计代码执行时间的方法吗欢迎评论区补充留言。