10

我正在尝试测量几种方法的执行时间。所以我想制作一个方法而不是多次重复相同的代码。

这是我的代码:

private void MeasureExecutionTime(Method m)
{
    startTime = System.nanoTime();
    try
    {
        m();
    }
    finally
    {
        endTime = System.nanoTime();
    }
    elapsedTime = endTime - startTime;
    System.out.println("This takes " + elapsedTime + " ns.");
}

假设我有myMethod(),我如何使用MeasureExecutionTime()来测量myMethod的执行时间?

4

6 回答 6

9

方法不是 Java 中的一等对象,因此它们不能作为参数传递。您可以使用将您的方法调用包装在一个扩展例如Runnable接口的烦人类中:

private void MeasureExecutionTime(Runnable r) {
    r.run();
}

...


MeasureExecutionTime(new Runnable() { public void run() { m(); } });
于 2011-05-19T15:30:12.970 回答
7

最简单的方法是传递一个接口。所以像

public interface CommonFuncs {

   public void execute();
   ... more functions

}

然后你可以拥有将 CommonFuncs 作为参数的方法。这些方法的实现可以调用该execute方法。

于 2011-05-19T15:28:24.620 回答
2

我同意@hvgotcodes,但是是的,这是可能的,虽然你不叫它 like m(),而是使用invoke(这意味着你可能应该传递另一个或两个参数......)。

于 2011-05-19T15:31:03.513 回答
2

您在正确的路径中,您需要传递 Method 对象、执行该方法的目标对象以及它采用的参数,然后将其调用到您的 try catch 中,例如:

private void MeasureExecutionTime(Method m, Object target, Object args) 
                            throws IllegalArgumentException, 
                                   IllegalAccessException, 
                                   InvocationTargetException
{
    long startTime = System.nanoTime();
    long endTime;
    try
    {
        m.invoke(target, args);
    }
    finally
    {
        endTime = System.nanoTime();
    }
    long elapsedTime = endTime - startTime;
    System.out.println("This takes " + elapsedTime + " ns.");
}
于 2011-05-19T15:31:59.953 回答
1

我有一个对象调用 Counter 基本上看起来像这样:

private long count;
private long errors;
private long duration;
private long errorDuration;

有两个“时间”方法用于计时方法,它们返回一些东西和其他无效的方法。

public <T> T time(ReturningRunnable<T> runnable) {
    long start = currentTimeMillis();
    T result = null;
    try {
        result = runnable.run();
    } catch (Throwable ex) {
        errorDuration += currentTimeMillis() - start;
        errors++;
        throw runtime(ex);
    }
    duration += currentTimeMillis() - start;
    count++;
    return result;
}

public void time(Runnable runnable) {
    time(new RunnableRunner(runnable));
}

我选择将异常重新抛出为运行时异常(因为我不喜欢检查异常),但您也可以让您的自定义 MyRunnable 接口抛出异常,然后捕获并重新抛出它们。这是上面的用法:

counter.time(new Runnable() {
    @Override
    public void run() {
        // Do something
    });

或者这个,在返回值的情况下:

return counter.time(new ReturningRunnable<Integer>() {
    @Override
    public Integer run() {
        return 1; // You get the idea
    });

我喜欢这个,因为我的计数器对象可以通过 JMX 公开并在我需要的地方注入。您可以通过反思来做您所要求的事情,但我认为那会很混乱(恕我直言)。

于 2011-05-19T15:34:53.713 回答
1

你可能会这样做:

private void MeasureExecutionTime(Method m)
{

    startTime = System.nanoTime();
    try
    {
        m.invoke(classObj, args);
    }
    finally
    {
        int endTime = System.nanoTime();
    }
    elapsedTime = endTime - startTime;
    System.out.println("This takes " + elapsedTime + " ns.");
}
于 2011-05-19T15:36:12.000 回答