草庐IT

别再用 System.currentTimeMillis() 统计耗时了,太 Low,StopWatch 好用到爆!

Java技术栈 2023-03-28 原文

背景

你还在用 System.currentTimeMillis... 统计耗时?

比如下面这段代码:

/**
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
@Test
public void jdkWasteTime() throws InterruptedException {
    long start = System.currentTimeMillis();
    Thread.sleep(3000);
    System.out.printf("耗时:%dms.", System.currentTimeMillis() - start);
}

System.currentTimeMillis...这种方式统计耗时确实是用的最多的,因为它不用引入其他的 JAR 包,JDK 就能搞定,但是它用起来有几个不方便的地方:

1)需要定义初始时间值,再用当前时间进行手工计算;

2)统计多个任务的耗时比较麻烦,如果 start 赋值搞错可能还会出现逻辑问题;

有没有其他的更好的替代方案呢?答案是肯定的:StopWatch

StopWatch

StopWatch 是一个统计耗时的工具类:

常用的 StopWatch 工具类有以下两种:

  • commons-lang3(Apache 提供的通用工具包)
  • spring-core(Spring 核心包)

虽然两个工具类的名称是一样的,但是用法大不相同,本文栈长就给大家分别演示下。

commons-lang3 提供的 StopWatch

引入依赖

commons-lang3 是 Apache 开源的通用工具包,需要额外引入 Maven 依赖:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>${commons-lang3.version}</version>
</dependency>

简单示例

创建一个 StopWatch 实例有以下 3 种方法:

1) 使用 new 关键字

StopWatch sw = new StopWatch();

2)使用 create 工厂方法

StopWatch sw = StopWatch.create();

3)使用 createStarted 方法

StopWatch sw = StopWatch.createStarted();

这个方法不但会创建一个实例,同时还会启动计时。

来看一个简单的例子:

// 创建一个 StopWatch 实例并开始计时
StopWatch sw = StopWatch.createStarted();

// 休眠1秒
Thread.sleep(1000);

// 1002ms
System.out.printf("耗时:%dms.\n", sw.getTime()); 

更多用法

接之前的示例继续演示。

暂停计时:

// 暂停计时
sw.suspend();

Thread.sleep(1000);

// 1000ms
System.out.printf("暂停耗时:%dms.\n", sw.getTime()); 

因为暂停了,所以还是 1000ms,暂停后中间休眠的 1000 ms 不会被统计。

恢复计时:

// 恢复计时
sw.resume();

Thread.sleep(1000);

// 2001ms
System.out.printf("恢复耗时:%dms.\n", sw.getTime()); 

因为恢复了,结果是 2001 ms,恢复后中间休眠的 1000 ms 被统计了。

停止计时:

Thread.sleep(1000);

// 停止计时
sw.stop();

Thread.sleep(1000);

// 3009ms
System.out.printf("总耗时:%dms.\n", sw.getTime()); 

停止计时前休眠了 1000ms,所以结果是 3009ms,停止计时后就不能再使用暂停、恢复功能了。

重置计时:

// 重置计时
sw.reset();

// 开始计时
sw.start();

Thread.sleep(1000);

// 1000ms
System.out.printf("重置耗时:%dms.\n", sw.getTime()); 

因为重置计时了,所以重新开始计时后又变成了 1000ms。

本文所有完整示例源代码已经上传:

https://github.com/javastacks/javastack

欢迎 Star 学习,后面 Java 示例都会在这上面提供!

Spring 提供的 StopWatch

来看一个简单的例子:

// 创建一个 StopWatch 实例
StopWatch sw = StopWatch("公众号Java技术栈:测试耗时");

// 开始计时
sw.start("任务1");

// 休眠1秒
Thread.sleep(1000);

// 停止计时
sw.stop();

// 1002ms
System.out.printf("任务1耗时:%d%s.\n", sw.getLastTaskTimeMillis(), "ms");

Spring 创建实例的方法就是 new,开始计时,以及获取时间需要手动 start、stop。

继续再新增 2 个任务:

Thread.sleep(1000);

sw.start("任务2");
Thread.sleep(1100);
sw.stop();

// 1100ms.
System.out.printf("任务2耗时:%d%s.\n", sw.getLastTaskTimeMillis(), "ms");

sw.start("任务3");
Thread.sleep(1200);
sw.stop();

// 1203ms.
System.out.printf("任务3耗时:%d%s.\n", sw.getLastTaskTimeMillis(), "ms");

// 3.309373456s.
System.out.printf("任务数量:%s,总耗时:%ss.\n", sw.getTaskCount(), sw.getTotalTimeSeconds());

Spring 一个重要的亮点是支持格式化打印结果:

System.out.println(sw.prettyPrint());

来看最后的输出结果:

不过有一点不友好的是,格式化结果显示的是纳秒,而且不能修改。。

实现原理

分别来看下 commons-lang3 和 Spring 的核心源码:

其实也都是利用了 JDK 中的 System 系统类去实现的,做了一系列封装而已。

总结

commons-lang3 工具包和 Spring 框架中的 StopWatch 都能轻松完成多个任务的计时以及总耗时,再也不要用手工计算耗时的方式了,手动计算如果 start 赋值错误可能还会出错。

当然,以上两个 StopWatch 的功能也远不止栈长介绍的,栈长介绍的这些已经够用了,更多的可以深入研究。

本文所有完整示例源代码已经上传:

https://github.com/javastacks/javastack

欢迎 Star 学习,后面 Java 示例都会在这上面提供!

总结一下这两种计时工具类优缺点:

1)commons-lang3 中的 StopWatch 的用法比 Spring 中的要更简单一些;

2)commons-lang3 中的 StopWatch 功能比 Spring 中的要更灵活、更强大一些,支持暂停、恢复、重置等功能;

3)Spring 提供每个子任务名称,以及按格式化打印结果功能,针对多任务统计时更好一点;

综上所述,个人推荐使用 commons-lang3 工具包中的,更灵活、更强大,如果不想额外引入包,也可以考虑 Spring 中的,根据自己的系统需求定。

所以,别再用 System.currentTimeMillis... 统计耗时了,太 low,赶紧分享转发下吧,规范起来!

好了,今天的分享就到这里了,后面栈长会分享更多好玩的 Java 技术和最新的技术资讯,关注公众号Java技术栈第一时间推送,我也将主流 Java 面试题和参考答案都整理好了,在公众号后台回复关键字 "面试" 进行刷题。

版权声明: 本文系公众号 "Java技术栈" 原创,转载、引用本文内容请注明出处,抄袭、洗稿一律投诉侵权,后果自负,并保留追究其法律责任的权利。

近期热文推荐:

1.1,000+ 道 Java面试题及答案整理(2022最新版)

2.劲爆!Java 协程要来了。。。

3.Spring Boot 2.x 教程,太全了!

4.别再写满屏的爆爆爆炸类了,试试装饰器模式,这才是优雅的方式!!

5.《Java开发手册(嵩山版)》最新发布,速速下载!

觉得不错,别忘了随手点赞+转发哦!

有关别再用 System.currentTimeMillis() 统计耗时了,太 Low,StopWatch 好用到爆!的更多相关文章

  1. C/C++好用的websocket库 - 2

    IntrductionLibwebsocketsisasimple-to-use,MIT-license,pureClibraryprovidingclientandserverforhttp/1,http/2,websockets,MQTTandotherprotocolsinasecurity-minded,lightweight,configurable,scalableandflexibleway.It’seasytobuildandcross-buildviacmakeandissuitablefortasksfromembeddedRTOSthroughmasscloudservi

  2. ruby - 导轨 3 : Creating app with internal plugin system - 2

    我想在Rails中使用插件系统创建一个应用程序。潜在用户应该能够上传(或更好地从存储库安装)一个插件并安装它,使我的应用程序能够做更多的事情。这应该在没有FTP/SSH/对服务器的任何低级别访问的情况下完成。关于如何在Rails3中完成它,是否有任何好的gems或教程? 最佳答案 你看过http://edgeguides.rubyonrails.org/plugins.html了吗??它似乎不是100%兼容Rails3,但它可以帮助您入门。我看过的大多数插件文章都涉及Rails2。 关于

  3. ruby - 如何获取我的 Sinatra 应用程序的代码覆盖率统计信息? - 2

    我编写了一个Sinatra应用程序(网站),我想收集网站代码的代码覆盖率信息。我是Ruby的新手,但Google告诉我rcov是一个很好的代码覆盖工具。不幸的是,我在网上可以找到的所有信息只显示了如何获取有关测试用例的代码覆盖率信息-我想要有关我的站点本身的代码覆盖率信息。我想要分析的特定站点文件位于“sdk”和“sdk/vendor”目录中,因此我通常使用“rubysite.rb”运行我的站点的地方我改为尝试以下操作:rcov-Isdk-Isdk/vendorsite.rb它显示了Sinatra启动文本,但随后立即退出,而不是像我的Sinatra应用程序通常那样等待网络请求。有人能告

  4. ruby-on-rails - 收集 Rails 应用程序使用统计信息的最佳方式 - 2

    我有一个Rails应用程序,用户可以在其中设置他们的域并在其中发布内容。我需要收集公共(public)流量统计信息,例如网页浏览量等。此功能的一个很好的例子是我作为客户可以看到的flickr使用统计信息。问题是收集使用信息的最佳方式是什么。应该通过解析日志文件来完成还是应该在运行时收集并存储在数据库中?是否有任何工具或Rails插件已经提供了此功能?此解决方案应该可以很好地扩展,即使每月有数千个域和数百万次网页浏览。 最佳答案 GoogleAnalytics可能是您最好的选择... 关于

  5. Unity 报错No ‘git‘ executable was found. Please install Git on your system then restart - 2

    亲测可用。Anerroroccurredwhileresolvingpackages:Projecthasinvaliddependencies: com.unity.xxx:No'git'executablewasfound.PleaseinstallGitonyour  systemthenrestartUnityandUnityHub在我们使用PackageManager时,Unity允许我们使用Git上的package(点击加号,选择addpackagefromgitURL,或者是直接在Asset/Packages/manifest.json中添加包名)。但是这种操作需要我们事先装好g

  6. ruby-on-rails - 有没有办法获取 Rails 服务器运行的耗时? - 2

    我只想在我的Rails项目中的某个地方以HTMLView将其打印出来,以及其他一些有用的信息。类似于“当前运行时间=4d11h54m2s”或“自2013年8月23日起运行”。令人惊讶的是,在任何地方都找不到有关此的任何信息。也许有一种通用的Rack方法可以做到这一点。 最佳答案 这其实很容易做到。创建一个文件,config/initializers/uptime.rb,包含:YourApplication::BOOTED_AT=Time.now这只是将当前时间与那个时间进行比较的情况,您可以使用time_ago_in_wordsra

  7. 详解Unity中的粒子系统Particle System (二) - 2

    前言上一篇我们简要讲述了粒子系统是什么,如何添加,以及基本模块的介绍,以及对于曲线和颜色编辑器的讲解。从本篇开始,我们将按照模块结构讲解下去,本篇主要讲粒子系统的主模块,该模块主要是控制粒子的初始状态和全局属性的,以下是关于该模块的介绍,请大家指正。目录前言本系列提要一、粒子系统主模块1.阅读前注意事项2.参考图3.参数讲解DurationLoopingPrewarmStartDelayStartLifetimeStartSpeed3DStartSizeStartSize3DStartRotationStartRotationFlipRotationStartColorGravityModif

  8. ruby - 从 Ruby 中的 "system"命令返回输出? - 2

    我必须从Ruby脚本执行shell命令,但我必须检索输出以便稍后在脚本中使用它。这是我的代码:output=system"herokucreate"#=>true但是系统命令返回一个bool值而不是输出。简单地说,系统“herokucreate”必须输出到我的屏幕(它确实如此)但也返回输出以便我可以处理它。 最佳答案 你可以使用output=`herokucreate`参见:http://ruby-doc.org/core/classes/Kernel.html 关于ruby-从Ruby

  9. ruby - "gem update --system"会将 rails 从 2.3.8 更新到 3.0 吗? - 2

    如果我有第二台计算机,我会这样做并看看-但我已经对它进行了微调,使其暂时不运行3.0......不想搞砸它。花了好几个小时才到这里。基本上-我想将rails保持在2.3.8一段时间......所以会gemupdate--system更新rails从版本2->3?我确实阅读了没有明确答案的文档,我猜它会,但是嘿,可能会学到一些新东西。否则,我会更新我拥有的每一个(8-1个)gem。谢谢... 最佳答案 gemupdate--system仅更新RubyGems。gemupdate会将所有已安装的gem更新到最新版本,因此会将Rails更

  10. ruby - 计算数组的统计信息 - 2

    我正在构建一个需要计算数据集统计信息的网络应用程序。我需要计算数组的百分位数、平均值、众数和其他统计函数。通常在Python中,我只会使用scipy、numpy或nltk,它们有一个巨大的stat数组函数库。我可以利用任何ruby​​gem或库来执行此操作吗?在没有任何现有库的情况下,是否有一种简单的方法可以在Python中进行数据处理,同时将我的应用程序保留在Ruby/Rails中? 最佳答案 如果你真的需要一个完整的统计库,看看statsample.否则你可能会发现descriptive_statistics成为一个不错的、轻量

随机推荐