关于java:Java程序员必备快速统计接口耗时小工具强烈推荐

32次阅读

共计 4173 个字符,预计需要花费 11 分钟才能阅读完成。

咱们常常须要统计一个办法的耗时,个别咱们会这样做:

public class Test {public static void main(String[] args) throws InterruptedException {long start = System.currentTimeMillis();
        // 睡眠 100ms,模仿工作耗时
        Thread.sleep(100L);
        long end = System.currentTimeMillis();
        System.out.println("耗时:" + (end - start)); // 输入 耗时:104
    }
}

这样做尽管简略间接,当咱们须要分段统计耗时的时候,一不留神就找不到开始工夫在哪了。而且也不能汇总后果,不能直观的看到每一步的耗时。

有一个简略的小工具,能够帮忙咱们非常容易的统计办法耗时。

名字叫 StopWatch,在常见的类库,例如 Spring、Apache Commons、Google Guava 都有这个工具,性能和实现都是大同小异,举荐应用 Spring 里的,能够更不便统计耗时的汇总后果。

把耗时代码换成 StopWatch 试一下:

public class Test {public static void main(String[] args) throws InterruptedException {
        // 创立统计工作
        StopWatch stopWatch = new StopWatch();
        // 开始计时
        stopWatch.start();
        // 睡眠 100ms,模仿工作耗时
        Thread.sleep(100L);
        // 完结计时
        stopWatch.stop();
        // 打印统计后果
        System.out.println(stopWatch.prettyPrint());
    }
}

输入后果是:

StopWatch '': running time (millis) = 104
-----------------------------------------
ms     %     Task name
-----------------------------------------
00104  100%  

只统计了一个工作的耗时,还不能展现出 StopWatch 劣势,上面一次统计多个工作的耗时:

public class CopyTest {public static void main(String[] args) {
        // 创立统计工作,并指定 ID
        StopWatch stopWatch = new StopWatch("Main 办法耗时");
        IntStream.rangeClosed(1, 10).forEach(index -> {
            // 开始计时,并指定工作名称,便于展现
            stopWatch.start("task" + index);
            // 睡眠 100ms,模仿工作耗时
            try {Thread.sleep(100L);
            } catch (InterruptedException e) { }
            // 完结计时
            stopWatch.stop();});
        // 打印统计后果
        System.out.println(stopWatch.prettyPrint());
    }
}

输入后果是:

StopWatch 'Main 办法耗时': running time (millis) = 1039
-----------------------------------------
ms     %     Task name
-----------------------------------------
00103  010%  task1
00107  010%  task2
00104  010%  task3
00104  010%  task4
00105  010%  task5
00102  010%  task6
00104  010%  task7
00102  010%  task8
00105  010%  task9
00103  010%  task10

打印出了每个工作的耗时,并统计了在总耗时所占百分比,曾经十分直观了。

这是怎么实现的呢?其实源码非常简单,就用一个 LinkedList 记录了每个工作的耗时:

public class StopWatch {

    // 总任务 ID
    private final String id;

    // 工作汇合
    private final List<TaskInfo> taskList = new LinkedList<TaskInfo>();

    private long startTimeMillis;

    private boolean running;

    private String currentTaskName;

    private TaskInfo lastTaskInfo;

    private long totalTimeMillis;

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

    public StopWatch(String id) {this.id = id;}

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

    // 开始计时,并记录开始工夫
    public void start(String taskName) throws IllegalStateException {if (this.running) {throw new IllegalStateException("Can't start StopWatch: it's already running");
        }
        this.running = true;
        this.currentTaskName = taskName;
        this.startTimeMillis = System.currentTimeMillis();}

    // 完结计时,统计耗时,并增加到 taskList 外面
    public void stop() throws IllegalStateException {if (!this.running) {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);
        this.taskList.add(lastTaskInfo);
        this.running = false;
        this.currentTaskName = null;
    }

    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();}

    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();}

    public double getTotalTimeSeconds() {return this.totalTimeMillis / 1000.0;}

    public TaskInfo[] getTaskInfo() {return this.taskList.toArray(new TaskInfo[this.taskList.size()]);
    }

    public String shortSummary() {return "StopWatch'" + getId() + "': running time (millis) =" + getTotalTimeMillis();}
        // 打印统计后果
    public String prettyPrint() {StringBuilder sb = new StringBuilder(shortSummary());
        sb.append('\n');
        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();}

    public static final class TaskInfo {
        private final String taskName;
        private final long timeMillis;
        TaskInfo(String taskName, long timeMillis) {
            this.taskName = taskName;
            this.timeMillis = timeMillis;
        }
    }
}

感觉怎么样?连忙应用起来吧。

正文完
 0