Java计算代码段执行时间的详细过程

目录
  • 前言
  • 场景
  • 代码实现
    • MethodBody 接口定义
    • CalcExecuteTimeResult 运行结果实体
    • ExecuteTemplate 执行模板定义
    • 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) {
        if (!SUPPORTED_TIME_UNIT.contains(timeUnit)) {
            throw new UnsupportedOperationException("不支持的时间单位:" + timeUnit);
        }
        if (TimeUnit.NANOSECONDS.equals(timeUnit)) {
            return System.nanoTime();
        }
        return System.currentTimeMillis();
    }
    /**
     * 当前支持的时间单位
     */
    private static final Set<TimeUnit> SUPPORTED_TIME_UNIT = Set.of(TimeUnit.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 executeTemplate;
    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.println(executeTimeResult);
    }
}

运行结果:

111
111
111
111
111
111
111
111
111
111
222
222
222
222
222
222
222
222
222
222
CalcExecuteTimeResult(costTime=[0, 1])

到此这篇关于Java计算代码段执行时间的详细过程的文章就介绍到这了,更多相关Java代码段执行时间内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java计算代码段执行时间的详细代码

    java里计算代码段执行时间可以有两种方法,一种是毫秒级别的计算,另一种是更精确的纳秒级别的计算. 一)毫秒级别计算时间 long startTime = System.currentTimeMillis(); /* 要计算执行时间的代码段 */ long endTime = System.currentTimeMillis(); System.out.println("代码段执行时间:" + (endTime - startTime) + "ms"); 二)更精确

  • Java计算代码段执行时间的详细过程

    目录 前言 场景 代码实现 MethodBody 接口定义 CalcExecuteTimeResult 运行结果实体 ExecuteTemplate 执行模板定义 CalcExecuteTimeContext 计算执行时间上下文 测试运行 前言 在日常开发功能时,同一种功能可能会有多种实现方式.我们需要做一个取舍. 最常见的条件就是性能.可读性.可维护性. 本篇文章,我们主要讨论“性能”. 场景 假设我们现在需要计算一段代码的运行时间. 最常见的写法是,在执行这段代码前,获得一下当前的时间戳,在

  • Java统计代码的执行时间的N种方法

    目录 方法一:System.currentTimeMillis 方法二:System.nanoTime 方法三:new Date 方法四:Spring StopWatch 方法五:commons-lang3 StopWatch 方法六:Guava Stopwatch 原理分析 1.Spring StopWatch 原理分析 2.Google Stopwatch 原理分析 结论 总结 知识扩展—Stopwatch 让统计更方便 在日常开发中经常需要测试一些代码的执行时间,但又不想使用向 JMH(J

  • vscode 配置java环境并调试运行的详细过程

    下载vscode以及安装jdk 度娘一大堆 这里不介绍 jdk最好安装jdk11及以上 vscode扩展插件有关 在vscode扩展插件中安装图示插件包,该包基本覆盖java所需的所有内容 新建一个vscode工程,并添加HelloJava.java文件 public class HelloJava{ public static void main(String[] args) { System.out.println("hello world"); } } PS:文件名要与类名一致

  • Java实现AWT四大事件的详细过程

    目录 窗体事件 鼠标事件 所触发的事件 键盘事件 动作事件 小结 常用事件的分类 Java AWT里面的事件可以简单的分为窗体事件(WindowEvent),鼠标事件(MouseEvent),键盘事件(KeyEvent),动作事件(ActionEvent)等事件. 窗体事件 窗体事件是GUI应用程序的基础,应用程序中通常是将其他的组件直接或间接的置于窗体中.在窗体中进行打开,关闭,激活,停用时,JDK提供了一个类WindowEvent用于表示这些窗体事件,定义了一个WindowListener接

  • C语言基础应用处理学生打分 计算时间 最少硬币问题详细过程

    第一题: 最少硬币问题(简单版) 假设有三种面值的硬币,分别为10.5.1.接收一个整数作为金额数,计算要达到该金额数,每个面值的硬币最少需要多少枚. 输出结果演示: 参考答案: #include <stdio.h> typedef struct StructrueMoneyBox { int n10; int n5; int n1; } MoneyBox; int main(void) { MoneyBox change = {0, 0, 0}; int face_value[4] = {1

  • Java实现红黑树(平衡二叉树)的详细过程

    目录 前言 红黑二叉查找树 2-3树 2-3树的插入操作 实现红黑二叉树 结尾 前言 在实现红黑树之前,我们先来了解一下符号表. 符号表的描述借鉴了Algorithms第四版,详情在:https://algs4.cs.princeton.edu/home/ 符号表有时候被称为字典,就如同英语字典中,一个单词对应一个解释,符号表有时候又被称之为索引,即书本最后将术语按照字母顺序列出以方便查找的那部分.总的来说,符号表就是将一个键和一个值联系起来,就如Python中的字典,JAVA中的HashMap

  • pytorch和tensorflow计算Flops和params的详细过程

    目录 pytorch和tensorflow计算Flops和params 1.只计算params 2.计算flops和params 3.tensorflow计算params和flops pytorch和tensorflow计算Flops和params 1.只计算params net = model() # 定义好的网络模型 total = sum([param.nelement() for param in net.parameters()]) print("Number of parameter

  • Java欧拉函数的计算代码详解

    欧拉函数 在数论,对正整数n,欧拉函数是小于或等于n的正整数中与n互质的数的数目(因此φ(1)=1).此函数以其首名研究者欧拉命名(Euler's totient function),它又称为Euler's totient function.φ函数.欧拉商数等. 例如φ(8)=4,因为1,3,5,7均和8互质. 从欧拉函数引伸出来在环论方面的事实和拉格朗日定理构成了欧拉定理的证明. 欧拉函数-百度百科. 前言 在数论,对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目(因此φ(1)=1).

  • 在VSCode里使用Jupyter Notebook调试Java代码的详细过程

    目录 什么是Jupyter Notebook? Jupyter Notebook主要优点 环境准备 下载 IJava 创建conda虚拟环境 搭建运行环境 测试 之前使用的那台电脑有点旧了,稍微跑一下程序就报内存不够.本来想考虑入手一台带GPU的新电脑,在商品浏览里的时候,考虑到钱包不够厚实.就选了家里另外一台配置稍微高一点的电脑拿来折腾. 平时我个人开发,主要还是在Eclipse上,新环境也装了装.其实平时学习的话,主要还是跑一跑代码段,不会跑大规模的项目,总有一种到楼下买个菜还要开车去的感觉

随机推荐