在工作中经常有统计某个方法的执行时间,比如项目中我们写了一个AOP,在AOP中定义了环绕通知用于向日志中打印相应的参数及方法执行的时间。最常用的方式就是记录一个开始时间,然后在记录结束时间,使用开始时间减去结束时间就可以得出方法执行的时间。如下:
public Object around(ProceedingJoinPoint pjd) throws Throwable {
log.info("环绕通知开始");
// 获取方法名
String className = pjd.getSignature().getClass().getName();
// 获取执行的方法名称
String methodName = pjd.getSignature().getName();
log.info("方法名称::{}", methodName);
// 定义返回参数
Object result = null;
// 记录开始时间
long start = System.currentTimeMillis();
// 获取方法参数
Object[] args = pjd.getArgs();
String params = "前端请求参数为:";
//获取请求参数集合并进行遍历拼接
for (Object object : args) {
params += object.toString() + ",";
}
params = params.substring(0, params.length() - 1);
//打印请求参数参数
log.info("{}类的{}的{}", className, methodName, params);
// 执行目标方法
result = pjd.proceed();
// 打印返回报文
log.info("方法返回为:{}", result);
// 获取执行完的时间
log.info("{}方法执行时长为:{}", methodName, (System.currentTimeMillis() - start));
log.info("环绕通知结束");
return result;
}
这种方式在统计单个任务的时候没有问题。假如我们有这样一个需求,在一个方法中我们调用了多个接口,需要统计每个接口消耗的时间及占比。如果还是使用上面的方法就比较麻烦,在阅读spirngboot源码的时候发现StopWatch可以很好的满足该需求,源码如下:
StopWatch 使用demo如下:
public class Test {
public static void main(String[] args) throws InterruptedException {
// 最原始的方法
long start = System.currentTimeMillis();
Thread.sleep(3000L);
long end = System.currentTimeMillis();
System.out.println("任务耗时:" + (end - start) + "毫秒");
//使用 StopWatch
StopWatch stopWatch = new StopWatch();
stopWatch.start("任务1");
Thread.sleep(3000L);
stopWatch.stop();
stopWatch.start("任务2");
Thread.sleep(2000L);
stopWatch.stop();
System.out.println("最后一个任务耗时:" + stopWatch.getLastTaskTimeMillis() + "毫秒");
System.out.println("最后一个任务名称:" + stopWatch.getLastTaskName());
System.out.println("所有任务耗时:" + stopWatch.getTotalTimeMillis() + "毫秒");
System.out.println("所有任务耗时:" + stopWatch.getTotalTimeSeconds() + "秒");
System.out.println(stopWatch.shortSummary());
//打印每个任务执行时间,以及占总时间百分比
System.out.println(stopWatch.prettyPrint());
System.out.println(stopWatch.toString());
}
}
执行结果如下: