StopWatch类功能增强

spring提供的StopWatch类可以帮助我们收集方法耗时,但是缺点是只能在一个方法内收集,不支持多个方法内统一收集

gitee地址

github地址

优化点:

1、可以在多线程下使用

2、可以跨方法使用

KStopWatch.class

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

public class KStopWatch {

    private final static ConcurrentHashMap counter = new ConcurrentHashMap();
    private final List completeTaskList;
    private final static KStopWatch stopWatch = new KStopWatch();
    private KStopWatch(){
        completeTaskList = new ArrayList(128);
    }

    public static KStopWatch getInstance(){
        return stopWatch;
    }

    public void start(String taskName){
        String key = taskName + ";" + Thread.currentThread().getId();
        Long[] times = new Long[2];
        times[0] = 0L;
        times[1] = System.currentTimeMillis();
        Long[] oldTime = counter.putIfAbsent(key, times);
        if(oldTime != null){
            if(oldTime[0] == null){
                oldTime[0] = 0L;
            }else{
                oldTime[0] += System.currentTimeMillis() - oldTime[1];
            }
            oldTime[1] = System.currentTimeMillis();
            counter.put(key, oldTime);
        }
    }

    public void stop(String taskName){
        String key = taskName + ";" + Thread.currentThread().getId();
        Long[] times = counter.get(key);
        if(times == null || times[1] == null){
            throw new RuntimeException("taskName:"+key+" not start!");
        }
        times[0] += System.currentTimeMillis() - times[1];
        completeTaskList.add(new KStopWatch.TaskInfo(key, times[0]));
        counter.remove(key);
    }

    @Override
    public synchronized String toString() {
        //StringBuilder sb = new StringBuilder("completeTask:" + completeTaskList.size() + "\n");
        StringBuilder sb = new StringBuilder("total:\n");
        Map totalMap = new HashMap(128);
        Map detailMap = new HashMap(128);
        for (int i = 0; i < completeTaskList.size(); i++) {
            TaskInfo taskInfo = completeTaskList.get(i);
            String method = taskInfo.getTaskName().split(";")[0];
            if(!totalMap.containsKey(method)){
                totalMap.put(method, 0L);
            }
            Long times = totalMap.get(method);
            times += taskInfo.getTimeSeconds();
            totalMap.put(method, times);

            if(!detailMap.containsKey(taskInfo.getTaskName())){
                detailMap.put(taskInfo.getTaskName(), 0L);
            }
            Long times1 = detailMap.get(taskInfo.getTaskName());
            times1 += taskInfo.getTimeSeconds();
            detailMap.put(taskInfo.getTaskName(), times1);

            completeTaskList.remove(taskInfo);
            i--;
        }
        sb.append(totalMap);
        sb.append("\n");
        sb.append("detail:\n");
        sb.append(detailMap);
        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;
        }

        public String getTaskName() {
            return this.taskName;
        }

        public long getTimeMillis() {
            return this.timeMillis;
        }

        public long getTimeSeconds() {
            return TimeUnit.MILLISECONDS.toSeconds(this.timeMillis);
        }

        public double getTimeMinutes() { return TimeUnit.MILLISECONDS.toMinutes(this.timeMillis); }
    }
}

测试类:KStopWatchTest.class

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class KStopWatchTest {

    public static void main(String[] args) throws InterruptedException {
        KStopWatchTest test = new KStopWatchTest();
        // 线程运行
        // test.threadTest(); 
        // 线程池运行
        test.threadPoolTest();
    }

    public void threadTest() throws InterruptedException {
        KStopWatch sw = KStopWatch.getInstance();
        for (int i = 0; i < 3; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    long st = System.currentTimeMillis();
                    sw.start("计算threadTest耗时");
                    try {
                        Thread.sleep((new Random().nextInt(2)+1)*1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    long ed = System.currentTimeMillis();
                    System.out.println(Thread.currentThread().getId() + "-耗时:" + TimeUnit.MILLISECONDS.toSeconds(ed-st) + " s");
                    sw.stop("计算threadTest耗时");
                }
            }).start();
        }

        Thread.sleep(11 * 1000);
        System.out.println(sw.toString());
    }

    public void threadPoolTest() throws InterruptedException {
        ExecutorService pool =
                new ThreadPoolExecutor(5, 5, 30L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
        ExecutorService pool1 =
                new ThreadPoolExecutor(5, 5, 30L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
        ExecutorService pool2 =
                new ThreadPoolExecutor(5, 5, 30L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
        KStopWatch sw = KStopWatch.getInstance();
        for (int i = 0; i < 10; i++) {
            pool.submit(() -> {
                long st = System.currentTimeMillis();
                sw.start("代码A");
                try {
                    Thread.sleep((new Random().nextInt(4)+1)*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                long ed = System.currentTimeMillis();
                //System.out.println(Thread.currentThread().getName() + "-耗时:" + TimeUnit.MILLISECONDS.toSeconds(ed-st) + " s");
                sw.stop("代码A");
            });
        }

        for (int i = 0; i < 10; i++) {
            pool1.submit(() -> {
                long st = System.currentTimeMillis();
                sw.start("代码B");
                try {
                    Thread.sleep((new Random().nextInt(4)+1)*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                long ed = System.currentTimeMillis();
                //System.out.println(Thread.currentThread().getName() + "-耗时:" + TimeUnit.MILLISECONDS.toSeconds(ed-st) + " s");
                sw.stop("代码B");
            });
        }

        for (int i = 0; i < 10; i++) {
            pool2.submit(() -> {
                long st = System.currentTimeMillis();
                sw.start("代码C");
                try {
                    Thread.sleep((new Random().nextInt(4)+1)*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                long ed = System.currentTimeMillis();
                //System.out.println(Thread.currentThread().getName() + "-耗时:" + TimeUnit.MILLISECONDS.toSeconds(ed-st) + " s");
                sw.stop("代码C");
            });
        }

        Thread.sleep(60 * 1000);
        System.out.println(KStopWatch.getInstance().toString());
        pool.shutdown();
        pool1.shutdown();
        pool2.shutdown();
    }
}

测试结果(单位是秒):

total:
{代码B=27, 代码C=29, 代码A=24}
detail:
{代码B;17=5, 代码B;16=6, 代码B;19=7, 代码B;18=5, 代码C;24=4, 代码C;25=8, 代码C;22=6, 代码C;23=6, 代码C;21=5, 代码A;15=7, 代码A;12=4, 代码A;11=4, 代码A;14=4, 代码A;13=5, 代码B;20=4}

你可能感兴趣的:(工具代码,java,spring,stopWatch)