Spring Boot源码实现StopWatch优雅统计耗时

首先我们先来介绍一下StopWatch是什么。

StopWatch是Spring Framework中用来计时的工具类,其设计思想源于Commons-lang中的StopWatch。其主要功能是帮助我们在开发过程中进行代码耗时的统计,方便我们进行性能优化。StopWatch提供了一系列操作,例如开始计时、停止计时以及记录过程中每个计时点的时间等。

接下来,我们就来详细讲解Spring Boot源码中StopWatch的实现过程。

1.定义类

首先,我们需要定义一个类来创建StopWatch对象。在Spring Boot中,我们可以通过以下方式来定义:

package org.springframework.boot;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class StopWatch {

    private String id;

    private boolean keepTaskList = true;

    private final List<TaskInfo> taskList = new ArrayList<>();

    private long startTimeMillis;

    private boolean running;

    private String currentTaskName;

    private TaskInfo lastTaskInfo;

    private int taskCount;

    private long totalTimeMillis;


    public StopWatch() {
        this("");
    }


    public StopWatch(String id) {
        this.id = (id != null ? id : "");
    }

    public String getId() {
        return this.id;
    }

}

2.开始计时

接着,我们需要在StopWatch中实现开始计时的方法。代码如下:

public void start() throws IllegalStateException {
    synchronized (this) {
        if (this.running) {
            throw new IllegalStateException("Can't start StopWatch: it's already running");
        }
        this.startTimeMillis = System.currentTimeMillis();
        this.running = true;
        this.currentTaskName = null;
        this.taskList.clear();
    }
}

在上述代码中,我们通过synchronized锁定当前实例,防止多线程环境下对StopWatch的可见性问题。然后我们判断当前是否正在计时,如果正在计时,则抛出IllegalStateException异常,否则开始计时。同时也初始化了一些状态,例如当前的任务名称和任务列表等。

3.停止计时

接下来,我们需要在StopWatch中实现停止计时的方法。代码如下:

public void stop() throws IllegalStateException {
    synchronized (this) {
        if (!this.running) {
            throw new IllegalStateException("Can't stop StopWatch: it's not running");
        }
        long lastTaskTimeMillis = System.currentTimeMillis() - this.startTimeMillis;
        this.totalTimeMillis += lastTaskTimeMillis;
        this.lastTaskInfo = new TaskInfo(this.currentTaskName, lastTaskTimeMillis);
        this.taskList.add(this.lastTaskInfo);
        ++this.taskCount;
        this.running = false;
        this.currentTaskName = null;
    }
}

与开始计时类似,我们也需要对当前实例进行锁定。然后我们判断当前是否正在计时,如果没有在计时,就抛出异常。这里我们记录了最后一次任务的时间,累加到总时间中,并且将最后一个任务的信息添加到任务列表中。

4.记录任务信息

在StopWatch中,我们还需要记录过程中每个计时点的时间。代码如下:

public void lap(String taskName) throws IllegalStateException {
    synchronized (this) {
        if (!this.running) {
            throw new IllegalStateException("Can't lap StopWatch: it's not running");
        }
        long lastTaskTimeMillis = System.currentTimeMillis() - this.startTimeMillis;
        this.totalTimeMillis += lastTaskTimeMillis;
        this.lastTaskInfo = new TaskInfo(this.currentTaskName, lastTaskTimeMillis);
        this.taskList.add(this.lastTaskInfo);
        ++this.taskCount;
        this.currentTaskName = taskName;
        this.startTimeMillis = System.currentTimeMillis();
    }
}

在这里,我们首先判断当前是否正在计时,如果没有在计时,则抛出异常。记录最后一个任务的时间,然后将最后一个任务的信息添加到任务列表中,并累加到总时间中。最后,我们将当前任务名称设置为指定的任务名称,并重新开始计时。

5.获取总时间

最后,我们需要在StopWatch中获取总时间。代码如下:

public long getTotalTimeMillis() {
    synchronized (this) {
        return this.totalTimeMillis;
    }
}

在这里,我们只需要返回记录的总时间即可。

至此,我们已经完成了Spring Boot源码中StopWatch的实现。接下来,我们可以通过以下两个示例来演示如何使用StopWatch:

示例1:统计方法执行时间

StopWatch stopWatch = new StopWatch();
stopWatch.start();

// 执行耗时任务
Thread.sleep(1000);

stopWatch.stop();
System.out.println("方法总耗时:" + stopWatch.getTotalTimeMillis() + "ms");

在这里,我们新建了一个StopWatch实例,开始计时,然后执行耗时任务,最后停止计时,并输出总耗时时间。

示例2:统计多个任务的处理时间

StopWatch stopWatch = new StopWatch();
stopWatch.start("任务一");
Thread.sleep(1000);
stopWatch.stop();

stopWatch.start("任务二");
Thread.sleep(2000);
stopWatch.stop();

System.out.println("任务一耗时:" + stopWatch.getTotalTimeMillis() + "ms");
System.out.println("任务二耗时:" + stopWatch.getLastTaskTimeMillis() + "ms");

在这里,我们通过StopWatch来统计多个任务的处理时间。首先,我们开始计时第一个任务,并执行任务,最后停止计时。然后开始计时第二个任务,执行任务,最后停止计时。最后,我们输出第一个任务和第二个任务的处理时间。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Boot源码实现StopWatch优雅统计耗时 - Python技术站

(0)
上一篇 2023年6月6日
下一篇 2023年6月6日

相关文章

  • C#泛型集合类System.Collections.Generic

    概述:C#泛型集合类System.Collections.Generic是.NET框架中最常用的一些类之一。泛型集合类可以存储不同类型的元素,并且支持各种常见的操作,如添加、删除、查找、排序等。泛型集合类通过定义泛型类型参数实现类型安全,这使得代码更加可读、可维护、可扩展。本文将介绍System.Collections.Generic泛型集合类的完整攻略,掌…

    C# 2023年5月15日
    00
  • ASP.NET MVC使用异步TPL模式

    ASP.NET MVC使用异步TPL模式的完整攻略如下: 什么是TPL TPL,即Task Parallel Library,是.NET Framework 4.0及以上版本的一个并发处理库,用于在不同线程之间并发执行任务,提高程序的并发执行能力和性能。 为什么使用TPL 使用TPL可以带来以下几个好处: 提高程序性能:多个任务并行执行可以利用多CPU、多核…

    C# 2023年5月31日
    00
  • C#在后台运行操作(BackgroundWorker用法)示例分享

    接下来我将详细讲解如何在C#中使用BackgroundWorker来实现后台运行操作。 BackgroundWorker简介 BackgroundWorker是一个轻量级的组件,可以用于让一些耗时的操作在后台线程中执行,而不会阻塞用户界面。它是多线程编程中常用的一种方式。 BackgroundWorker有三个主要事件:DoWork事件、ProgressCh…

    C# 2023年5月15日
    00
  • C#实现简易计算器功能(1)(窗体应用)

    下面是“C#实现简易计算器功能(1)(窗体应用)”的完整攻略,包含两个实例说明。 标题 C#实现简易计算器功能(1)(窗体应用) 简介 本文将介绍如何使用C#语言实现简易计算器功能。在这个教程中,我们将学习如何创建一个窗体应用程序,并使用C#语言来实现基本的计算器功能。 步骤 步骤1. 创建新项目 首先,打开Visual Studio,并点击“创建新项目”选…

    C# 2023年6月6日
    00
  • C# Base 64 编码/解码实现代码

    下面我会详细讲解“C# Base 64 编码/解码实现代码”的完整攻略: 简介 Base 64 编码是一种常见的用于传输二进制数据的编码方式,通常用于在网络传输中将二进制的数据转换为 ASCII 字符串,方便传输和存储。C# 中提供了对 Base 64 编码和解码的支持,使用非常方便。 Base 64 编码实现 C# 中实现 Base 64 编码的方法非常简…

    C# 2023年5月31日
    00
  • 深入多线程之:用Wait与Pulse模拟一些同步构造的应用详解

    下面是对“深入多线程之:用Wait与Pulse模拟一些同步构造的应用详解”的完整攻略: 简介 在多线程编程中,一些同步构造往往是必需的,以便协调不同线程之间的操作,避免出现竞态条件等问题。这篇文章将介绍用Wait和Pulse模拟一些同步构造的方法。 Wait和Pulse概述 Wait和Pulse是.NET Framework中用于协调同步操作的两个重要方法。…

    C# 2023年6月7日
    00
  • C# String.Contains()方法: 检查字符串是否包含指定的子字符串

    C#中String.Contains()的作用与使用方法 在C#中,String.Contains()是一个字符串方法,用于判断一个字符串是否包含指定的子字符串,如果包含则返回true,否则返回false。这个方法通常在字符串查找和替换中使用。 使用方法 String.Contains()方法的基本使用方法如下: string str = "Hel…

    C# 2023年4月19日
    00
  • c#数据类型基础

    C#数据类型基础 一、基础数据类型 C#中的基本数据类型有以下几种: 整型:int、long、short、byte、sbyte、uint、ulong、ushort 浮点型:float、double 字符型:char 布尔型:bool 对象型:object 字符串型:string 空类型:void 其中,整型数据类型可以存储整数;浮点型数据类型可以存储带小数点…

    C# 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部