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

 更新时间:2023年02月07日 10:54:47   作者:你家宝宝  
java里计算代码段执行时间可以有两种方法,一种是毫秒级别的计算,另一种是更精确的纳秒级别的计算,这篇文章主要介绍了java计算代码段执行时间,需要的朋友可以参考下

前言

在日常开发功能时,同一种功能可能会有多种实现方式。我们需要做一个取舍。

最常见的条件就是性能、可读性、可维护性。

本篇文章,我们主要讨论“性能”。

场景

假设我们现在需要计算一段代码的运行时间。

最常见的写法是,在执行这段代码前,获得一下当前的时间戳,在执行这段代码后,获取一下当前的时间戳,然后俩时间相减,就是花费时间了。

但有时,我们需要将这段代码执行多次。

这种场景是,执行的时间戳很小,没有可比性。比如执行一段代码,运行时间是 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代码段执行时间内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 从Android源码剖析Intent查询匹配的实现

    从Android源码剖析Intent查询匹配的实现

    这篇文章主要介绍了从Android源码剖析Intent查询匹配的实现,Intent部分的源码为Java代码,需要的朋友可以参考下
    2015-07-07
  • PowerJob的DispatchStrategy方法工作流程源码解读

    PowerJob的DispatchStrategy方法工作流程源码解读

    这篇文章主要为大家介绍了PowerJob的DispatchStrategy方法工作流程源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • 详解ZXing-core生成二维码的方法并解析

    详解ZXing-core生成二维码的方法并解析

    本文给大家介绍ZXing-core生成二维码的方法并解析,主要用到goggle发布的jar来实现二维码功能,对此文感兴趣的朋友一起学习吧
    2016-05-05
  • SpringAMQP的使用方式案例详解

    SpringAMQP的使用方式案例详解

    这篇文章主要介绍了SpringAMQP的使用方式,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2024-01-01
  • java并发访问重复请求过滤问题

    java并发访问重复请求过滤问题

    本篇文章给大家分享了关于java并发访问重复请求过滤的相关问题以及解决方法,对此有需要的朋友参考学习下。
    2018-05-05
  • Java 线程池ExecutorService详解及实例代码

    Java 线程池ExecutorService详解及实例代码

    这篇文章主要介绍了Java 线程池ExecutorService详解及实例代码的相关资料,线程池减少在创建和销毁线程上所花的时间以及系统资源的开销.如果不使用线程池,有可能造成系统创建大量线程而导致消耗系统内存以及”过度切换“
    2016-11-11
  • 浅谈Java中OutOfMemoryError问题产生原因

    浅谈Java中OutOfMemoryError问题产生原因

    本文主要介绍了浅谈Java中OutOfMemoryError问题产生原因,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06
  • java 容器的快速失败(fast-fail)机制

    java 容器的快速失败(fast-fail)机制

    Java容器的快速失败机制是一种在迭代过程中检测并处理集合并发修改的特性,该机制适用于ArrayList、HashMap等集合类,本文就来介绍一下java 容器的快速失败(fast-fail)机制,感兴趣的可以了解一下
    2024-11-11
  • SpringBoot集成Caffeine缓存的实现步骤

    SpringBoot集成Caffeine缓存的实现步骤

    Caffeine cache是一个针对Java的高性能缓存库。在本文中,我们将介绍它与Spring Boot如何一起使用。
    2021-05-05
  • Spring Batch 入门示例

    Spring Batch 入门示例

    本文将向您展示如何使用Spring Boot创建一个的Spring Batch的Hello World示例。对和我一样入门的有一定的帮助,感兴趣的小伙伴们可以参考一下
    2021-06-06

最新评论