使用Java 8执行计时方法

时间:2016-11-01 02:28:15

标签: java java-8 closures method-reference

我已阅读How do I time a method's execution in Java?并了解计时方法执行的常规可能性(执行启动/停止计时器,使用方面等)。

我想知道Java 8的新方法引用和lambdas是否会为达到以下目标带来任何帮助。

普通代码:

String r;
r = methodCall("foo","bar");

在性能调优期间,将代码修改为类似的内容,以测量执行方法所花费的时间

String r;
time(() -> {
  r = methodCall("foo", "bar"); // doesn't work as r needs to be effectively final
});

我看到我能做到

String r;
r = time1(() -> 
    methodCall("foo", "bar)
);

(注意结尾处缺少的分号),使用像

这样的time1方法
public static <R> R time1(Supplier<R> s){
    long start = System.currentTimeMillis();
    R result  = s.get();
    System.out.println("Execution took " + (System.currentTimeMillis() - start));
    return result;
}

或者我可以做

r = time2(this::methodCall, "foo", "bar");

使用像

这样的time2方法
public static <A,B,R> R time2(BiFunction<A, B, R> f, A first, B second){
    long start = System.currentTimeMillis();
    R result = f.apply(first, second);
    System.out.println("Execution took " + (System.currentTimeMillis() - start));
    return result;
}

没有回报价值,我可以做得更好

time3(() -> {
    System.out.println("hello");
});

(注意,分号存在)和time3一样

public static void time3(Runnable r){
    long start = System.currentTimeMillis();
    r.run();
    System.out.println("Execution took " + (System.currentTimeMillis() - start));
}

当我有返回值时,是否有更好的解决方案?

我需要关闭才能做到吗?

1 个答案:

答案 0 :(得分:6)

你仍然可以包装方法调用,只为没有产生任何东西的东西返回null:

public <R> R timing(Supplier<R> operation) {
    long start = System.nanoTime();
    R result  = operation.get();
    System.out.printf("Execution took %dms\n", TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start));
    return result;
}

public void timing(Runnable operation) {
    this.timing(() -> { operation.run(); return null; });
}

然后这些电话基本相同:

String r = timing(() -> methodCall("foo", "bar"));
timing(() -> System.out.println("Hello"));

实际上,如果您想要使用方法参数/引用,您需要了解Java的Function api和方法签名之间的关系。

基本上,你不能动态地重新映射所有方法参数并对方法进行直接的“命名”引用(以及对参数进行varargs),你能做的最好/最接近的方法是覆盖{{1}你在n看到的参数(或继续制作自定义BiFunction的参数。也许有一天我们会有类似于C#的“varargs”泛型操作,但在此之前我们无法做到这一点类似于FunctionalInterface