记录JAVA代码执行耗时工具及示例
一、功能说明及效果展示
1. 支持多任务计时,每个子任务多段计时
2. 效果展示:
/** * 四种统计方案: * 时间差统计 * StopWatchTool * Function * AutoCloseable */ System: 51 101 test StopWatchTool: ----------------------------------------- taskName taskChildName ms ----------------------------------------- set : set first 52 get : get first 51 test Function: ----------------------------------------- taskName taskChildName ms ----------------------------------------- set : set first 50 second 50 get : get first 50 second 50 test AutoCloseable: ----------------------------------------- taskName taskChildName ms ----------------------------------------- set : set first 51 second 52 get : get first 50 second 51
二、实现方式
1. 计时工具:StopWatchTool
2. 包装计时器:StopWatchHolder,为了支持function调用
三、测试代码
/** * 四种统计方案: * 时间差统计 * StopWatchTool * Function * AutoCloseable */ public static void main(String[] args) throws InterruptedException { //时间差统计 Long start = System.currentTimeMillis(); Thread.sleep(50); Long end1 = System.currentTimeMillis(); Thread.sleep(50); Long end2 = System.currentTimeMillis(); System.out.println((end1 - start)); System.out.println((end2 - start)); //StopWatchTool StopWatchTool stopWatch = StopWatchTool.newInstance("test StopWatchTool"); stopWatch.start("set", "first"); Thread.sleep(50); stopWatch.stop(); stopWatch.start("get", "first"); Thread.sleep(50); stopWatch.stop(); System.out.println(stopWatch.prettyPrint()); //Function stopWatch = StopWatchTool.newInstance("test Function"); StopWatchHolder.run(stopWatch, "set", "first", s -> { try { Thread.sleep(50); } catch (Exception e) { e.printStackTrace(); } }); //同一个任务,两段计时 StopWatchHolder.run(stopWatch, "set", "second", s -> { try { Thread.sleep(50); } catch (Exception e) { e.printStackTrace(); } }); StopWatchHolder.run(stopWatch, "get", "first", g -> { try { Thread.sleep(50); } catch (Exception e) { e.printStackTrace(); } }); //同一个任务,两段计时 StopWatchHolder.run(stopWatch, "get", "second", g -> { try { Thread.sleep(50); } catch (Exception e) { e.printStackTrace(); } }); System.out.println(stopWatch.prettyPrint()); //AutoCloseable stopWatch = StopWatchTool.newInstance("test AutoCloseable"); try(StopWatchTool ignored = stopWatch.startByChain("set", "first")) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } try(StopWatchTool ignored = stopWatch.startByChain("set", "second")) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } try(StopWatchTool ignored = stopWatch.startByChain("get", "first")) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } try(StopWatchTool ignored = stopWatch.startByChain("get", "second")) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(stopWatch.prettyPrint()); }
四、源代码
public class StopWatchHolder { /** * 有返回值调用 */ public static <T> T run(StopWatchTool stopWatch, String taskName, String taskChildName, Supplier<T> supplier) { try { stopWatch.start(taskName, taskChildName); return supplier.get(); } finally { stopWatch.stop(); } } /** * 无返回值调用 */ public static void run(StopWatchTool stopWatch, String taskName, String taskChildName, IntConsumer function) { try { stopWatch.start(taskName, taskChildName); function.accept(0); } finally { stopWatch.stop(); } } }
public class StopWatchTool implements AutoCloseable { /** * 任务ID */ private String id; /** * Start time of the current task. */ private long startMs; /** * Name of the current task. */ @Nullable private String currentTaskName; /** * Second Name of the current task. */ @Nullable private String currentTaskChildName; //记录任务信息,同一任务,可以分段计时 private final Map<String, List<TaskInfo>> taskMap = new HashMap<>(); public static StopWatchTool newInstance(String id) { return new StopWatchTool(id); } @Override public void close() { this.stop(); } public StopWatchTool(String id) { this.id = id; } /** * 开始时间差类型指标记录,如果需要终止,请调用 {@link #stop()} * * @param taskName 指标名 */ public void start(String taskName, String taskChildName) throws IllegalStateException { if (this.currentTaskName != null) { throw new IllegalStateException("Can't start StopWatchTool: it's already running"); } this.currentTaskName = taskName; this.currentTaskChildName = taskChildName; this.startMs = System.currentTimeMillis(); } /** * 返回this,支持链式调用 * * @param taskName * @return * @throws IllegalStateException */ public StopWatchTool startByChain(String taskName, String taskChildName) throws IllegalStateException { if (this.currentTaskName != null) { throw new IllegalStateException("Can't start StopWatchTool: it's already running"); } this.currentTaskName = taskName; this.currentTaskChildName = taskChildName; this.startMs = System.currentTimeMillis(); return this; } /** * 终止时间差类型指标记录,调用前请确保已经调用 */ public void stop() throws IllegalStateException { if (this.currentTaskName == null) { throw new IllegalStateException("Can't stop TraceWatch: it's not running"); } long lastTime = System.currentTimeMillis() - this.startMs; TaskInfo info = new TaskInfo(this.currentTaskName, this.currentTaskChildName, lastTime); this.taskMap.computeIfAbsent(this.currentTaskName, e -> new LinkedList<>()).add(info); this.currentTaskName = null; } /** * 直接记录指标数据,不局限于时间差类型 * * @param taskName 指标名 * @param data 指标数据 */ public void record(String taskName, String taskChildName, Object data) { TaskInfo info = new TaskInfo(taskName, taskChildName, data); this.taskMap.computeIfAbsent(taskName, e -> new LinkedList<>()).add(info); } /** * 打印 * * @return */ public String prettyPrint() { String whiteStr = " "; StringBuilder sb = new StringBuilder(id).append(":").append("\n"); if (this.taskMap.isEmpty()) { sb.append("No task info kept"); } else { sb.append("-----------------------------------------\n"); sb.append("taskName taskChildName ms \n"); sb.append("-----------------------------------------\n"); for (Map.Entry<String, List<TaskInfo>> entry : taskMap.entrySet()) { sb.append(entry.getKey()); sb.append(" : "); for (int i = 0; i < entry.getValue().size(); i++) { TaskInfo taskInfo = entry.getValue().get(i); if (i == 0) { sb.append(taskInfo.getTaskName()).append(whiteStr); } sb.append(taskInfo.getTaskChildName()).append(whiteStr); sb.append(taskInfo.getData()).append(whiteStr); } sb.append("\n"); } } return sb.toString(); } /** * 任务信息 */ public static final class TaskInfo { private final String taskName; private final String taskChildName; private final Object data; public TaskInfo(String taskName, String taskChildName, Object data) { this.taskName = taskName; this.taskChildName = taskChildName; this.data = data; } public String getTaskName() { return taskName; } public String getTaskChildName() { return taskChildName; } public Object getData() { return data; } } }