如何获得方法的执行时间? 是否有Timer实用程序类来计时任务所需的时间等?

在谷歌上的大多数搜索都返回调度线程和任务的计时器的结果,这不是我想要的。


当前回答

为此,我们使用了AspectJ和Java注释。如果我们需要知道一个方法的执行时间,我们可以简单地注释它。更高级的版本可以使用自己的日志级别,可以在运行时启用和禁用。

public @interface Trace {
  boolean showParameters();
}

@Aspect
public class TraceAspect {
  [...]
  @Around("tracePointcut() && @annotation(trace) && !within(TraceAspect)")
  public Object traceAdvice ( ProceedingJintPoint jP, Trace trace ) {

    Object result;
    // initilize timer

    try { 
      result = jp.procced();
    } finally { 
      // calculate execution time 
    }

    return result;
  }
  [...]
}

其他回答

这可能不是您想让我说的,但是这是AOP的一个很好的用法。在您的方法周围使用代理拦截器,并在其中进行计时。

遗憾的是,AOP的什么、为什么和如何超出了这个答案的范围,但这就是我可能会做的事情。

编辑:如果你有兴趣的话,这里有一个Spring AOP的链接可以帮助你入门。这是Iive在java中遇到的最容易访问的AOP实现。

另外,考虑到其他人的简单建议,我应该补充一点:AOP适用于不希望时间之类的东西侵入代码的情况。但在很多情况下,这种简单易行的方法是可以的。

正如“skaffman”所说,使用AOP或您可以使用运行时字节码编织,就像使用单元测试方法覆盖工具透明地向调用的方法添加计时信息一样。

您可以查看开源工具(如Emma (http://downloads.sourceforge.net/emma/emma-2.0.5312-src.zip?modtime=1118607545&big_mirror=0))使用的代码。另一个开源覆盖工具是http://prdownloads.sourceforge.net/cobertura/cobertura-1.9-src.zip?download。

如果你最终做到了你所设定的目标,请用你的ant task/jars与社区分享。

纯Java SE代码,不需要添加依赖项,使用TimeTracedExecuter:

public static void main(String[] args) {

    Integer square = new TimeTracedExecutor<>(Main::calculateSquare)
                .executeWithInput("calculate square of num",5,logger);

}
public static int calculateSquare(int num){
    return num*num;
}

会产生这样的结果:

信息:计算num的平方需要3毫秒

自定义可重用类:TimeTracedExecutor

import java.text.NumberFormat;
import java.time.Duration;
import java.time.Instant;
import java.util.function.Function;
import java.util.logging.Logger;

public class TimeTracedExecutor<T,R> {
    Function<T,R> methodToExecute;

    public TimeTracedExecutor(Function<T, R> methodToExecute) {
        this.methodToExecute = methodToExecute;
    }

    public R executeWithInput(String taskDescription, T t, Logger logger){
        Instant start = Instant.now();
        R r= methodToExecute.apply(t);
        Instant finish = Instant.now();
        String format = "It took %s milliseconds to "+taskDescription;
        String elapsedTime = NumberFormat.getNumberInstance().format(Duration.between(start, finish).toMillis());
        logger.info(String.format(format, elapsedTime));
        return r;
    }
}

我们也可以使用Apache公共的StopWatch类来测量时间。

示例代码

org.apache.commons.lang.time.StopWatch sw = new org.apache.commons.lang.time.StopWatch();

System.out.println("getEventFilterTreeData :: Start Time : " + sw.getTime());
sw.start();

// Method execution code

sw.stop();
System.out.println("getEventFilterTreeData :: End Time : " + sw.getTime());

我基本上做的是这种方法的变体,但是考虑到热点编译的工作方式,如果您想要获得准确的结果,您需要抛弃前几个度量,并确保您在真实世界(阅读特定于应用程序的)应用程序中使用该方法。

如果JIT决定编译它,您的数字将会有很大的变化。所以要注意