6

Assume I am having such code snippets:

try {
   // code I need to wrap to be a helper
   long t0 = System.nanoTime();
   obj.doSomething();   // a void function
   long t1 = System.nanoTime();
   Logger.info("doSomthing takes {} nanoseconds", t1-t0);
}  catch (IOException ex) {
   Logger.error("something wrong happened");
}



// another code 

try {
    long t0 = System.nanoTime();
    obj.doAnotherThing();   // void function 
    long t1 = System.nanoTime();
    Logger.info("doSomthing takes {} nanoseconds", t1-t0);
}  catch (IOException ex) {
   Logger.error("something wrong happened");
}

So my question is actually how I can pass that void function as a parameter to a helper function, so that I can avoid redundant code for measuring the execution time of the function.


Follow Up: what if doSomething can throw IOException

In this case how should I invoke the function in the lambda world if I don't want to catch the exception in labmda.

Thanks

Lubor
  • 989
  • 3
  • 10
  • 33

3 Answers3

6

You can use a Runnable:

public void timeThis(Runnable runnable) {
    long t0 = System.nanoTime();
    runnable.run();
    long t1 = System.nanoTime();
    Logger.info("Execution took {} nanoseconds", t1 - t0);
}

You can then pass the function you want to run as an argument to timeThis:

timeThis(() -> obj.doSomething());

If obj.doSomething() happens to throw an IOException like you mentioned below, you can simply catch it within the body of the Runnable:

timeThis(() -> {
    try {
        obj.doSomething();
    } catch (IOException e) {
        e.printStackTrace();
    }
});

Note: This is not a proper benchmark. See: How do I write a correct micro-benchmark in Java?

Jacob G.
  • 28,856
  • 5
  • 62
  • 116
0

Though you got a relevant answer yet for exception handling part, I would recommend using JOOL library from JOOQ. It provides a handy set of FunctionaInterface up to 16 parameters. It also provides CheckedRunnable which allows the checked and unchecked exceptions to be thrown out of run method which could be handled as per your requirement.

So,

public void timeThis(Runnable runnable) {
    long t0 = System.nanoTime();
    runnable.run();
    long t1 = System.nanoTime();
    Logger.info("Execution took {} nanoseconds", t1 - t0);
}

will become:-

public void timeThis(CheckedRunnable runnable) {
    long t0 = System.nanoTime();
    runnable.run();
    long t1 = System.nanoTime();
    Logger.info("Execution took {} nanoseconds", t1 - t0);
}

And now you use it like below:-

try {
    timeThis(() -> {
        obj.doSomething();
   });
  } catch (IOException e) {
        e.printStackTrace();
  }

Observe that you don't have to handle the exception twice as are able to throw exception outside the lambda expression.

Hope it helps!

Vinay Prajapati
  • 7,199
  • 9
  • 45
  • 86
-3

Try using Java Reflection methods. https://docs.oracle.com/javase/tutorial/reflect/member/methodInvocation.html The wrapper function can take Method as input wherein Method value is initialized in caller. Within wrapper function use invoke to call the passed method.

ESR
  • 1