java代码优化,需要获取关键行耗时?
6 个回答
历史文章(文章累计450+) 《 国内最全的Spring Boot系列之一 》《 国内最全的Spring Boot系列之二 》《 国内最全的Spring Boot系列之三 》《 国内最全的Spring Boot系列之四 》《 国内最全的Spring Boot系列之 五 》 走进MyBatis源码一探Spring扩展点「知识点多多」「扩展点实战系列」- 第449篇
走进SpringBoot源码吃透Spring扩展点「扩展点实战系列」- 第450篇 5个月的精华:Spring/SpringBoot扩展点手册:手册在手,编码无忧:全网独一份 - 第451篇 SpringBoot添加外部jar包及打包(亲测有效) - 第452篇 SpringBoot引入外部jar包,项目打包成war包发布(亲测有效) - 第453篇
SpringBoot中使用Spring-Retry重试框架 - 第454篇
悟纤:最近代码逻辑,添加了很多的耗时的代码,感觉写的不是很好,师傅有更好的方案吗?
师傅:这个倒是有一个秒表StopWatch,可以稍微优化代码。
悟纤:那师傅介绍一下,让徒儿也增长下功力。
师傅:要不我直接把内里传给你吧。
悟纤:那最好不过了。
师傅:你想太多了。
悟纤:看来是电视看多了,这个时代,增加内力还得靠自己,木有办法,宝宝苦,宝宝累,宝宝好难受。
师傅:这个或许是你老了之后,你值得回忆的地方。
悟纤:那也是噢~
导读
如果想知道一个方法的执行耗时时长,一般的思路是:记录开始时间,执行业务代码,记录结束时间,方法的耗时就等于=结束时间-开始时间。这种方式可以实现基本的统计需求,如果要统计各个任务的占比,那么代码的复杂度就会增加,当然你封装出来一个类专门来处理执行耗时类。
如果使用了Spring框架,那么Spring已经提供了一个秒表工具StopWatch。
一、Java原生方式
这种方式最最简单,最好理解,经常会这么来写:
public void test1() throws InterruptedException {
long startTime = System.currentTimeMillis(); //获取开始时间
//函数主体代码
//...
TimeUnit.SECONDS.sleep(1);
long endTime = System.currentTimeMillis(); //获取结束时间
System.out.println("程序运行时间:" + (endTime - startTime) + "ms");
}
大多数时候我们使用ms来表示即可,但是这么写缺乏灵活性。倘若我们要展示成纳秒、秒、甚至分钟,还得我们自己处理(把毫秒值拿来进行转换~ )
当然可能到了JDK8以后,我们这么做能变得稍微灵活一些:可以这么处理:
public void test2() throws InterruptedException {
Instant start = Instant.now();
//doSomething();
TimeUnit.SECONDS.sleep(1);
Instant end = Instant.now();
Duration duration = Duration.between(start, end);
System.out.println("程序运行时间(毫秒) = " + duration.toMillis());
System.out.println("程序运行时间(纳秒) = " + duration.toNanos());
}
这个比上面灵活度强一些,但还是有一定的缺点:步骤稍显复杂,总体上还是不够优雅,也不是那么的灵活,多个任务的时候编写不方便。
那么本文针对此问题介绍一个工具:StopWatch执行时间监视器。借助它来统计我们程序的执行时间,带给非常多的方便和优雅。
二、秒表StopWatch
工具类StopWatch,秒表工具,执行时间监视器,用来统计任务的耗时的工具类。
2.1 工具类提供者
不单单只有spring提供了这个工具类,apache,google也提供了:
com.google.common.base.Stopwatch;
org.apache.commons.lang3.time.StopWatch;
springframework.util.StopWatch;
2.2 工具类使用
对于Spring StopWatch的使用很简单,直接看下代码:
public void test3() throws InterruptedException {
StopWatch stopWatch = new StopWatch("用户注册");
//启动任务一
stopWatch.start("保存用户信息");
//执行业务逻辑
TimeUnit.SECONDS.sleep(1);
stopWatch.stop();
//启动任务二
stopWatch.start("创建用户钱包信息");
//执行业务逻辑
TimeUnit.SECONDS.sleep(2);
stopWatch.stop();
//会输出所有任务的信息
System.out.println(stopWatch.prettyPrint());
// 只输出总的:StopWatch '用户注册': running time = 3004621914 ns
//System.out.println(stopWatch.shortSummary());