专栏首页CoffeeLandSpringframwork.Util之StopWatch 多任务计时
原创

Springframwork.Util之StopWatch 多任务计时

Table of contents

  • StopWatch intro
  • StopWatch 源码分析
  • StopWartch Demo

StopWatch intro

StopWatch是spring框架提供的一个util, 用来做多任务的计时, 隐藏了System.currentTimeMillis()的使用, 增加应用程序的可读性, 但是他不是为线程安全来设计的

官方文档

Simple stop watch, allowing for timing of a number of tasks,
 exposing total running time and running time for each named task.
Conceals use of System.currentTimeMillis(), improving the readability of application code and reducing the likelihood of calculation errors.
Note that this object is not designed to be thread-safe and does not use synchronization.
This class is normally used to verify performance during proof-of-concepts 
and in development, rather than as part of production applications.

StopWatch 源码分析

思路

要分段保存每个task的运行时间, 需要封装一个对象来存放task的运行时间, 即taskName 和 taskTotalTime,

还需要一个totoalTime来存储使用task的运行时间, 所以来看的stopwatch的源码

源码分析

public class StopWatch {

	// 标记这次stopwatch的id
	/**
	 * Identifier of this stop watch.
	 * Handy when we have output from multiple stop watches
	 * and need to distinguish between them in log or console output.
	 */
	private final String id;

	private boolean keepTaskList = true;
	
	//用来存储每个task的信息, taskInfo由taskName 和 totoalTime组成
	private final List<TaskInfo> taskList = new LinkedList<>();

	/** Start time of the current task. */
	private long startTimeMillis;

	/** Name of the current task. */
	@Nullable
	private String currentTaskName;

	@Nullable
	private TaskInfo lastTaskInfo;
	
	
	private int taskCount;

	/** Total running time. */
	private long totalTimeMillis;


	/**
	 * Construct a new stop watch. Does not start any task.
	 */
	public StopWatch() {
		this("");
	}

	/**
	 * Construct a new stop watch with the given id.
	 * Does not start any task.
	 * @param id identifier for this stop watch.
	 * Handy when we have output from multiple stop watches
	 * and need to distinguish between them.
	 */
	public StopWatch(String id) {
		this.id = id;
	}


	/**
	 * Return the id of this stop watch, as specified on construction.
	 * @return the id (empty String by default)
	 * @since 4.2.2
	 * @see #StopWatch(String)
	 */
	public String getId() {
		return this.id;
	}

	/**
	 * Determine whether the TaskInfo array is built over time. Set this to
	 * "false" when using a StopWatch for millions of intervals, or the task
	 * info structure will consume excessive memory. Default is "true".
	 */
	public void setKeepTaskList(boolean keepTaskList) {
		this.keepTaskList = keepTaskList;
	}


	/**
	 * Start an unnamed task. The results are undefined if {@link #stop()}
	 * or timing methods are called without invoking this method.
	 * @see #stop()
	 */
	public void start() throws IllegalStateException {
		start("");
	}

	/**
	 * Start a named task. The results are undefined if {@link #stop()}
	 * or timing methods are called without invoking this method.
	 * @param taskName the name of the task to start
	 * @see #stop()
	 */
	public void start(String taskName) throws IllegalStateException {
		if (this.currentTaskName != null) {
			throw new IllegalStateException("Can't start StopWatch: it's already running");
		}
		this.currentTaskName = taskName;
		this.startTimeMillis = System.currentTimeMillis();
	}

	/**
	 * Stop the current task. The results are undefined if timing
	 * methods are called without invoking at least one pair
	 * {@code start()} / {@code stop()} methods.
	 * @see #start()
	 */
	public void stop() throws IllegalStateException {
		if (this.currentTaskName == null) {
			throw new IllegalStateException("Can't stop StopWatch: it's not running");
		}
		long lastTime = System.currentTimeMillis() - this.startTimeMillis;
		this.totalTimeMillis += lastTime;
		this.lastTaskInfo = new TaskInfo(this.currentTaskName, lastTime);
		if (this.keepTaskList) {
			this.taskList.add(this.lastTaskInfo);
		}
		++this.taskCount;
		this.currentTaskName = null;
	}

	/**
	 * Return whether the stop watch is currently running.
	 * @see #currentTaskName()
	 */
	public boolean isRunning() {
		return (this.currentTaskName != null);
	}

	/**
	 * Return the name of the currently running task, if any.
	 * @since 4.2.2
	 * @see #isRunning()
	 */
	@Nullable
	public String currentTaskName() {
		return this.currentTaskName;
	}


	/**
	 * Return the time taken by the last task.
	 */
	public long getLastTaskTimeMillis() throws IllegalStateException {
		if (this.lastTaskInfo == null) {
			throw new IllegalStateException("No tasks run: can't get last task interval");
		}
		return this.lastTaskInfo.getTimeMillis();
	}

	/**
	 * Return the name of the last task.
	 */
	public String getLastTaskName() throws IllegalStateException {
		if (this.lastTaskInfo == null) {
			throw new IllegalStateException("No tasks run: can't get last task name");
		}
		return this.lastTaskInfo.getTaskName();
	}

	/**
	 * Return the last task as a TaskInfo object.
	 */
	public TaskInfo getLastTaskInfo() throws IllegalStateException {
		if (this.lastTaskInfo == null) {
			throw new IllegalStateException("No tasks run: can't get last task info");
		}
		return this.lastTaskInfo;
	}


	/**
	 * Return the total time in milliseconds for all tasks.
	 */
	public long getTotalTimeMillis() {
		return this.totalTimeMillis;
	}

	/**
	 * Return the total time in seconds for all tasks.
	 */
	public double getTotalTimeSeconds() {
		return this.totalTimeMillis / 1000.0;
	}

	/**
	 * Return the number of tasks timed.
	 */
	public int getTaskCount() {
		return this.taskCount;
	}

	/**
	 * Return an array of the data for tasks performed.
	 */
	public TaskInfo[] getTaskInfo() {
		if (!this.keepTaskList) {
			throw new UnsupportedOperationException("Task info is not being kept!");
		}
		return this.taskList.toArray(new TaskInfo[0]);
	}


	/**
	 * Return a short description of the total running time.
	 */
	public String shortSummary() {
		return "StopWatch '" + getId() + "': running time (millis) = " + getTotalTimeMillis();
	}

	/**
	 * Return a string with a table describing all tasks performed.
	 * For custom reporting, call getTaskInfo() and use the task info directly.
	 */
	public String prettyPrint() {
		StringBuilder sb = new StringBuilder(shortSummary());
		sb.append('\n');
		if (!this.keepTaskList) {
			sb.append("No task info kept");
		}
		else {
			sb.append("-----------------------------------------\n");
			sb.append("ms     %     Task name\n");
			sb.append("-----------------------------------------\n");
			NumberFormat nf = NumberFormat.getNumberInstance();
			nf.setMinimumIntegerDigits(5);
			nf.setGroupingUsed(false);
			NumberFormat pf = NumberFormat.getPercentInstance();
			pf.setMinimumIntegerDigits(3);
			pf.setGroupingUsed(false);
			for (TaskInfo task : getTaskInfo()) {
				sb.append(nf.format(task.getTimeMillis())).append("  ");
				sb.append(pf.format(task.getTimeSeconds() / getTotalTimeSeconds())).append("  ");
				sb.append(task.getTaskName()).append("\n");
			}
		}
		return sb.toString();
	}

	/**
	 * Return an informative string describing all tasks performed
	 * For custom reporting, call {@code getTaskInfo()} and use the task info directly.
	 */
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder(shortSummary());
		if (this.keepTaskList) {
			for (TaskInfo task : getTaskInfo()) {
				sb.append("; [").append(task.getTaskName()).append("] took ").append(task.getTimeMillis());
				long percent = Math.round((100.0 * task.getTimeSeconds()) / getTotalTimeSeconds());
				sb.append(" = ").append(percent).append("%");
			}
		}
		else {
			sb.append("; no task info kept");
		}
		return sb.toString();
	}


	/**
	 * Inner class to hold data about one task executed within the stop watch.
	 */
	public static final class TaskInfo {
		
		//taskName
		private final String taskName;
		
		// task的时间统计
		private final long timeMillis;

		TaskInfo(String taskName, long timeMillis) {
			this.taskName = taskName;
			this.timeMillis = timeMillis;
		}

		/**
		 * Return the name of this task.
		 */
		public String getTaskName() {
			return this.taskName;
		}

		/**
		 * Return the time in milliseconds this task took.
		 */
		public long getTimeMillis() {
			return this.timeMillis;
		}

		/**
		 * Return the time in seconds this task took.
		 */
		public double getTimeSeconds() {
			return (this.timeMillis / 1000.0);
		}
	}

}

StopWartch Demo

下面的方法用于统计

package mytest;

import org.springframework.util.StopWatch;

public class StopWatchDemo
{
    public static void main(String[] args) {
        StopWatch stopWatch = new StopWatch("myTest");

        stopWatch.start("thread1");
        StopWatchDemo.performTask1();
        stopWatch.stop();


        stopWatch.start("thread2");
        StopWatchDemo.performTask2();
        stopWatch.stop();
        System.out.println("total time: " + stopWatch.getTotalTimeSeconds() + " seconds");

        // prettyPrint() return a string with a table describing all tasks performed. For custom reporting, call getTaskInfo() and use the
        // task info directly.
        System.out.println("\n1. prettyPrint Result: " + stopWatch.prettyPrint());

        // Return a short description of the total running time.
        System.out.println("2. Short Summary: " + stopWatch.shortSummary());

        // Return the number of tasks timed.
        System.out.println("3. Total Task Count: " + stopWatch.getTaskCount());

        // Return the name of this task.
        System.out.println("4. Last Task Name: " + stopWatch.getLastTaskInfo().getTaskName());
    }

    private static void performTask1() {

        Runnable myRunnable = new Runnable() {

            public void run() {
                System.out.println(" Task 1 running");
            }
        };

        Thread crunchifyThread = new Thread(myRunnable);
        crunchifyThread.start();

    }

    private static void performTask2() {

        System.out.println(" Task 2 running \n");
        for (int i = 1; i <= 5; i++) {
            try {
                Thread.sleep(2000);
                System.out.println("Running Loop # " + i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("");
    }
}

喜欢我的文章, 请关注和点赞我的专栏, 可以最早查看我的文章, 感谢支持:)

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Spring IOC的理解

    Sping IoC is Inversion of Control. 控制反转.

    CoffeeLand
  • springboot 1.5.20.RELEASE可能会将http请求变成https

    系统的有一个写log的微服务A, spring boot的version是2.1.5.RELEASE

    CoffeeLand
  • 网络编程之TCP/IP

    tcp的三次握手是指client与server端通过发送http请求,建立tcp连接, 分为三个步骤

    CoffeeLand
  • PHP 使用协同程序实现合作多任务(一)

    PHP 5.5 一个比较好的新功能是实现对生成器和协同程序的支持。对于生成器,PHP的文档和各种其他的博客文章已经有了非常详细的讲解。协同程序相对受到的关注就少...

    后端技术探索
  • 聊聊maxwell的BootstrapController

    maxwell-1.25.1/src/main/java/com/zendesk/maxwell/bootstrap/BootstrapController.j...

    codecraft
  • 解惑:这个SPARK任务是数据倾斜了吗?

    健身回来的路上,看到微信群里聊技术,一群有问了一个神奇的问题,具体可以看如下截图:

    Spark学习技巧
  • python:celery

    问题:Received unregistered task of type 'app.task.analysis_aggregation.analysis_ag...

    Damon@yang
  • 聊聊maxwell的BootstrapController

    maxwell-1.25.1/src/main/java/com/zendesk/maxwell/bootstrap/BootstrapController.j...

    codecraft
  • 51多任务系统,可以运行

    图中可以看出,调用rtos_wait(100)后,PC=PC+3=0x0163,SP=SP+2;把PC值压栈,可以参考LCALL addr16这条汇编指令

    用户4645519
  • 哗众取宠还是确有其事?基因编辑婴儿背后疑点重重

    昨日(11月26日),人民网报道了世界首例基因编辑婴儿诞生的新闻,一时之间在全球引起轩然大波,研究者贺建奎被推上风口浪尖。

    镁客网

扫码关注云+社区

领取腾讯云代金券