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

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


当前回答

使用Java 8的新API中的即时和持续时间,

Instant start = Instant.now();
Thread.sleep(5000);
Instant end = Instant.now();
System.out.println(Duration.between(start, end));

输出,

PT5S

其他回答

使用AOP/AspectJ和来自jcabi-aspects的@Loggable注释,你可以简单而紧凑地完成:

@Loggable(Loggable.DEBUG)
public String getSomeResult() {
  // return some value
}

对该方法的每个调用都将发送到SLF4J日志记录工具,具有DEBUG日志记录级别。每个日志消息都将包括执行时间。

如果java有更好的功能支持就好了,这样需要测量的动作就可以被包装到一个块中:

measure {
   // your operation here
}

在java中,这可以通过匿名函数来完成,看起来太冗长了

public interface Timer {
    void wrap();
}


public class Logger {

    public static void logTime(Timer timer) {
        long start = System.currentTimeMillis();
        timer.wrap();
        System.out.println("" + (System.currentTimeMillis() - start) + "ms");
    }

    public static void main(String a[]) {
        Logger.logTime(new Timer() {
            public void wrap() {
                // Your method here
                timeConsumingOperation();
            }
        });

    }

    public static void timeConsumingOperation() {
        for (int i = 0; i<=10000; i++) {
           System.out.println("i=" +i);
        }
    }
}

这里有很多有效的答案,它们都是在方法中实现的。为了制作一个通用的计时方法,我通常有一个timing类,它由以下内容组成。

public record TimedResult<T>(T result, Duration duration) {}

public static Duration time(Runnable r) {
    var s = Instant.now();
    r.run();
    var dur = Duration.between(s, Instant.now());
    return dur;
}

public static <T> TimedResult<T> time(Callable<T> r) throws Exception {
    var s = Instant.now();
    T res = r.call();
    var dur = Duration.between(s, Instant.now());
    return new TimedResult<>(res, dur);
}

这足够通用,可以传递Runnable或Callable对象。

Duration result = Timing.time(() -> {
    // do some work.
});

TimedResult<String> result = Timing.time(() -> {
    // do some work.
    return "answer";
});

Duration timeTaken = result.duration();
String answer = result.result();

nanotime()是一个非常精确的系统实用程序,用于测量执行时间。但是要注意,如果运行在抢占式调度器模式(默认),这个实用程序实际上测量的是时钟时间,而不是CPU时间。因此,您可能会注意到每次运行的执行时间值是不同的,这取决于系统负载。如果您需要CPU时间,我认为在实时模式下运行您的程序就可以了。您必须使用RT linux。链接:使用Linux进行实时编程

Spring提供了一个实用工具类org.springframework.util。秒表,根据JavaDoc:

简单的秒表,允许计时多项任务,暴露 每个指定任务的总运行时间和运行时间。

用法:

StopWatch stopWatch = new StopWatch("Performance Test Result");

stopWatch.start("Method 1");
doSomething1();//method to test
stopWatch.stop();

stopWatch.start("Method 2");
doSomething2();//method to test
stopWatch.stop();

System.out.println(stopWatch.prettyPrint());

输出:

StopWatch 'Performance Test Result': running time (millis) = 12829
-----------------------------------------
ms     %     Task name
-----------------------------------------
11907  036%  Method 1
00922  064%  Method 2

方面:

@Around("execution(* my.package..*.*(..))")
public Object logTime(ProceedingJoinPoint joinPoint) throws Throwable {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    Object retVal = joinPoint.proceed();
    stopWatch.stop();
    log.info(" execution time: " + stopWatch.getTotalTimeMillis() + " ms");
    return retVal;
}