计时器之StopWatch

一、StopWatch 简介

1.1 StopWatch 是什么?

StopWatchorg.springframework.util 包下的一个工具类,通过它可方便的对程序执行时间进行统计。

1.2 简单使用

public class StopWatchTest {


    @Test
    public void test() throws InterruptedException {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("task_01");
        Thread.sleep(3);
        stopWatch.stop();
        stopWatch.start("task_02");
        Thread.sleep(2);
        stopWatch.stop();
        stopWatch.start("task_03");
        Thread.sleep(4);
        stopWatch.stop();
        System.out.println(stopWatch.prettyPrint());
    }

}

控制台输出:

StopWatch '': running time = 10659200 ns
---------------------------------------------
ns         %     Task name
---------------------------------------------
003353500  031%  task_01
002327200  022%  task_02
004978500  047%  task_03

二、StopWatch 源码解析

2.1 初始化 StopWatch

提供了两种构造函数用于初始化 StopWatch

// 用于区分秒表的主键
private final String id;

// 默认主键为空
public StopWatch() {
	this("");
}

// 指定秒表主键
public StopWatch(String id) {
	this.id = id;
}

2.2 启动 StopWatch

提供两种启动方式,当需要统计多个任务时,需要指定任务名称

// 当前任务名
private String currentTaskName;
// 统计开始时间
private long startTimeNanos;

public void start() throws IllegalStateException {
	start("");
}

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.startTimeNanos = System.nanoTime();
}

2.3 停止 StopWatch

// 执行的任务个数
private int taskCount;
// 总执行时间
private long totalTimeNanos;
// 是否保留任务信息
private boolean keepTaskList = true;
// 最近一次执行的任务信息
private TaskInfo lastTaskInfo;
// 执行的任务清单列表
private final List<TaskInfo> taskList = new LinkedList<>();

public void stop() throws IllegalStateException {
	if (this.currentTaskName == null) {
		throw new IllegalStateException("Can't stop StopWatch: it's not running");
	}
	long lastTime = System.nanoTime() - this.startTimeNanos;
	this.totalTimeNanos += lastTime;
    
	this.lastTaskInfo = new TaskInfo(this.currentTaskName, lastTime);    
	if (this.keepTaskList) {
		this.taskList.add(this.lastTaskInfo);
	}
    
	++this.taskCount;
	this.currentTaskName = null;
}

2.4 TaskInfo 对象结构

public static final class TaskInfo {
	// 任务名称
	private final String taskName;
	// 总耗时
	private final long timeNanos;
	......
}	

2.5 格式化输出

public String prettyPrint() {
	StringBuilder sb = new StringBuilder(shortSummary());
	sb.append('
');
	if (!this.keepTaskList) {
		sb.append("No task info kept");
	}
	else {
		sb.append("---------------------------------------------
");
		sb.append("ns         %     Task name
");
		sb.append("---------------------------------------------
");
		NumberFormat nf = NumberFormat.getNumberInstance();
		nf.setMinimumIntegerDigits(9);
		nf.setGroupingUsed(false);
		NumberFormat pf = NumberFormat.getPercentInstance();
		pf.setMinimumIntegerDigits(3);
		pf.setGroupingUsed(false);
		for (TaskInfo task : getTaskInfo()) {
			sb.append(nf.format(task.getTimeNanos())).append("  ");
			sb.append(pf.format((double) task.getTimeNanos() / getTotalTimeNanos())).append("  ");
			sb.append(task.getTaskName()).append("
");
		}
	}
	return sb.toString();
}
原文地址:https://www.cnblogs.com/markLogZhu/p/12492779.html