目录
- 前言
- 场景
- 代码实现
- MethodBody 接口定义
- CalcExecuteTimeResult 运行结果实体
- ExecuteT编程emplate 执行模板定义
- CalcExecuteTimeContext 计算执行时间上下文
- 测试运行
前言
在日常开发功能时,同一种功能可能会有多种实现方式。我们需要做一个取舍。
最常见的条件就是性能、可读性、可维护性。
本篇文章,我们主要讨论“性能”。
场景
假设我们现在需要计算一段代码的运行时间。
最常见的写法是,在执行这段代码前,获得一下当前的时间戳,在执行这段代码后,获取一下当前的时间戳,然后俩时间相减,就是花费时间了。
但有时,我们需要将这段代码执行多次。
这种场景是,执行的时间戳很小,没有可比性。比如执行一段代码,运行时间是 0 或者 2毫秒。
这种时候你可能会说,那就用一个for循环,执行多次,计算平均时间就好了。
问题来了,如果这种相似的操作,写的多了呢,用的地方很多呢?
我们现在就需要将它给写成一套模板,只需要简单的填充参数,调用,就能实现上述的功能。
代码实现
MethodBody 接口定义
这个接口主要是用于填充代码段,因此设计为函数式接口,方便调用。
package org.feng.calc; /** * 运行的方法内容:使用Lambda * * @version V1.0 */ @FunctionalInterface public interface MethodBody { void run(); }
CalcExecuteTimeResult 运行结果实体
package org.feng.calc; import lombok.Data; import Java.util.ArrayList; import java.util.List; /** * 计算执行时间的结果保存 * * @version V1.0 */ @Data public class CalcExecuteTimeResult { /** * 执行代码花费的时间 */ private List<Long> costTime; public CalcExecuteTimeResult(int size) { costTime = new ArrayList<>(size); } }
ExecuteTemplate 执行模板定义
package org.feng.calc; import lombok.Getter; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; /** * 执行模板 * * @version V1.0 */ public class ExecuteTemplate { private final List<MethodBody> methodBodyList; @Getter private CalcExecuteTimeResult calcExecuteTimeResult; public ExecuteTemplate() { this.methodBodyList = new ArrayList<>(); } public void addMethod(MethodBody methodBody) { methodBodyList.add(methodBody); } /** * 执行 * * @param timeUnit 时间单位 * @param frequency 频次-单个方法{@link MethodBody}实例执行的次数 */ void process(TimeUnit timeUnit, long frequency) { this.calcExecuteTimeResult = new CalcExecuteTimeResult(methodBodyList.size()); List<Long> costTime = calcExecuteTimeResult.getCostTime(); for (MethodBody methodBody : methodBodyList) { long startTime = getTime(timeUnit); for (int i = 0; i < frequency; i++) { methodBody.run(); } long endTime = getTime(timeUnit); costTime.add(endTime - startTime); } } private long getTime(TimeUnit timeUnit) { http://www.devze.com if (!SUPPORTED_TIME_UNIT.contains(timeUnit)) { throw new UnsupportedOperationException("不支持的时间单位:" + timeUnit); } if (TimeUnit.NANOSECONDS.equals(timeUnit)) { return System.nanoTime(); } return System.currentTimeMillis(); } /**开发者_Js入门 * 当前支持的时间单位 */ private static final Set<TimeUnit> SUPPORTED_TIME_UNIT = Set.of(TimeUniphpt.MILLISECONDS, TimeUnit.NANOSECONDS); }
CalcExecuteTimeContext 计算执行时间上下文
package org.feng.calc; import lombok.Setter; import lombok.experimental.Accessors; import java.util.concurrent.TimeUnit; /** * 计算执行时间-上下文 * * @version V1.0 */ @Setter @Accessors(chain = true) public class CalcExecuteTimeContext { private TimeUnit timeUnit; private Long frequency; private ExecuteTemplate executeTejavascriptmplate; public CalcExecuteTimeResult run() { executeTemplate.process(timeUnit, frequency); return executeTemplate.getCalcExecuteTimeResult(); } public void addMethod(MethodBody methodBody){ executeTemplate.addMethod(methodBody); } }
测试运行
package org.feng.calc; import java.util.concurrent.TimeUnit; /** * 测试运行 * * @version v1.0 */ public class Client { public static void main(String[] args) { // 初始化上下文:设置每个方法执行的次数,以及计算时间时使用的时间单位,执行模板 CalcExecuteTimeContext context = new CalcExecuteTimeContext() .setFrequency(2L) .setTimeUnit(TimeUnit.MILLISECONDS) .setExecuteTemplate(new ExecuteTemplate()); context.addMethod(() -> { System.out.println(111); System.out.println(111); System.out.println(111); System.out.println(111); System.out.println(111); }); context.addMethod(() -> { System.out.println(222); System.out.println(222); System.out.println(222); System.out.println(222); System.out.println(222); }); // 计算得到方法运行的结果 CalcExecuteTimeResult executeTimeResult = context.run(); System.out.printlnjavascript(executeTimeResult); } }
运行结果:
111
111111111111111111111111111222222222222222222222222222222CalcExecuteTimeResult(costTime=[0, 1])
到此这篇关于Java计算代码段执行时间的详细过程的文章就介绍到这了,更多相关Java代码段执行时间内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
精彩评论