当前位置:   article > 正文

StopWatch—— 优雅的程序计时器_stopwatch 计时

stopwatch 计时

​​​

StopWatch—— 优雅的程序计时器

程序计时器

在我们的开发过程中,为了更好的监测系统,接口,业务的运行情况,我们一般都会监测程序运行的时间,最初的时候我们是使用System.currentTimeMillis()获得开始和结束时间再进行相减从而获得程序运行时间,但是这种方式很繁琐也不够简洁,清晰。

StopWatch

介绍

StopWatch在Spring,Apache,hutool工具包中都有,里边的实现原理都差不多,只不过有一些API的调用和使用不太一样。

我们先来看一下StopWatch的使用:

相信看过SpringBoot源码的同学对这个应该并不陌生,在SpringBoot程序启动的时候,就用到了StopWatch:

  1. public ConfigurableApplicationContext run(String... args) {
  2. stopWatch = new StopWatch();// 声明一个StopWatch实例
  3. stopWatch.start();//任务启动
  4. ……
  5. stopWatch.stop();// 任务停止
  6. return context;
  7. }

看SpringBoot的例子可以知道,StopWatch的使用基本分为三步:创建实例,启动,停止。但是作为spring的工具类,StopWatch会这么简单吗?当然不会。

我们来看一下具体的使用:

  1. public static void main(String[] args) {
  2. // 构造方法的参数表示的是StopWatch实例的id,标志着实例的身份
  3. StopWatch watch = new StopWatch("StopWatch-Learning");
  4. String id = watch.getId();
  5. System.out.println("StopWatch 的id: " + id);
  6. // 启动任务,test为任务的名字
  7. watch.start("test");
  8. // 获取StopWatch是否正在运行
  9. boolean running = watch.isRunning();
  10. System.out.println("是否正在运行" + running);
  11. // 任务停止
  12. watch.stop();
  13. // 获取任务的名字
  14. String lastTaskName = watch.getLastTaskName();
  15. System.out.println("StopWatch任务的名字: " + lastTaskName);
  16. long lastTaskTimeNanos = watch.getLastTaskTimeNanos();// 任务运行时间 纳秒
  17. // long lastTaskTimeMillis = watch.getLastTaskTimeMillis(); // 任务运行时间 微妙
  18. System.out.println("任务" + lastTaskName + "运行了" + lastTaskTimeNanos + "ns");
  19. }

运行结果:

  1. StopWatch 的id: StopWatch-Learning
  2. 是否正在运行true
  3. StopWatch任务的名字: test
  4. 任务test运行了29000ns

我们还可以同时定义两个任务:

  1. public static void main(String[] args) {
  2. // 构造方法的参数表示的是StopWatch实例的id,标志着实例的身份
  3. StopWatch watch = new StopWatch("StopWatch-Learning");
  4. watch.start("test1");
  5. // 任务停止
  6. watch.stop();
  7. // 获取任务的名字
  8. String lastTaskName = watch.getLastTaskName();
  9. long task1TimeNanos = watch.getLastTaskTimeNanos();// 任务运行时间 纳秒
  10. // long lastTaskTimeMillis = watch.getLastTaskTimeMillis(); // 任务运行时间 微妙
  11. System.out.println("task1" + lastTaskName + "运行了" + task1TimeNanos + "ns");
  12. watch.start("test2");
  13. watch.stop();
  14. long task2TimeNanos = watch.getLastTaskTimeNanos();
  15. System.out.println("task2" + lastTaskName + "运行了" + task2TimeNanos + "ns");
  16. int count = watch.getTaskCount();
  17. System.out.println("一共启动了" + count + "个任务");
  18. long totalTimeNanos = watch.getTotalTimeNanos();
  19. System.out.println("一共运行了" + totalTimeNanos + "ns");
  20. }

运行结果:

  1. task1test1运行了2200ns
  2. task2test1运行了300ns
  3. 一共启动了2个任务
  4. 一共运行了2500ns
  5. StopWatch 'StopWatch-Learning': running time = 2500 ns

对了还有一个方法prettyPrint(),这个方法可以帮助我们把输出的语句打印的更加好看!

  1. public static void main(String[] args) {
  2. // 构造方法的参数表示的是StopWatch实例的id,标志着实例的身份
  3. StopWatch watch = new StopWatch("StopWatch-Learning");
  4. watch.start("test1");
  5. // 任务停止
  6. watch.stop();
  7. // 获取任务的名字
  8. String lastTaskName = watch.getLastTaskName();
  9. long task1TimeNanos = watch.getLastTaskTimeNanos();// 任务运行时间 纳秒
  10. // long lastTaskTimeMillis = watch.getLastTaskTimeMillis(); // 任务运行时间 微妙
  11. System.out.println("task1" + lastTaskName + "运行了" + task1TimeNanos + "ns");
  12. System.out.println("^^^^^^^^^^^^^^^^^^^^分割线^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
  13. String info = watch.prettyPrint();
  14. System.out.println(info);
  15. }

运行结果:

  1. task1test1运行了2200ns
  2. ^^^^^^^^^^^^^^^^^^^^分割线^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  3. StopWatch 'StopWatch-Learning': running time = 2200 ns
  4. ---------------------------------------------
  5. ns % Task name
  6. ---------------------------------------------
  7. 000002200 100% test1

使用下来是不是很方便,丝滑,而且很清晰。

原理

我们看一下start()方法:

  1. public void start(String taskName) throws IllegalStateException {
  2. if (this.currentTaskName != null) {
  3. throw new IllegalStateException("Can't start StopWatch: it's already running");
  4. }
  5. this.currentTaskName = taskName;
  6. this.startTimeNanos = System.nanoTime();
  7. }

在任务开始的时候使用了 System.nanoTime()获取当前时间的纳秒时间戳,其实和我们之前使用System.currentTimeMillis()是一样的。

再来看一下stop()方法:

  1. public void stop() throws IllegalStateException {
  2. if (this.currentTaskName == null) {
  3. throw new IllegalStateException("Can't stop StopWatch: it's not running");
  4. }
  5. long lastTime = System.nanoTime() - this.startTimeNanos;
  6. this.totalTimeNanos += lastTime;
  7. this.lastTaskInfo = new TaskInfo(this.currentTaskName, lastTime);
  8. if (this.keepTaskList) {
  9. this.taskList.add(this.lastTaskInfo);
  10. }
  11. ++this.taskCount;
  12. this.currentTaskName = null;
  13. }

也是获取当前时间再减去开始时间,计算的时间差。和我们最开始说的currentTimeMillis本质上是一样的。只不过它的时间粒度更加细,是纳秒级别的。

突然有一种恍然大悟的感觉,这不和刚开始说的方法一样吗,不就是currentTimeMillis的改造版吗?但是就是因为改造的很好,我们可以很简单,很巧妙的计算任务的时间。

最巧妙的是我们可以给StopWatch创建一个id标志着它的身份,给每一个任务起一个名字,随时开始,停止,自动计算每一个任务,所有任务的时间差,还有一个自动格式化的结果的API,更加的美观,大气。在开发中对于多任务计算时长,很容易看错导致计算不准确,而StopWatch对于多任务优势就更加的明显。

既然StopWatch这么好用,还在等什么,还不用起来?今天的分享就到这里了,以后还会有更多的技术分享,欢迎大家的关注哦!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/511888
推荐阅读
相关标签
  

闽ICP备14008679号