Time Limitation on Method Execution in Java

I’m currently running some experiments.  I am running a lot of experiments, and they may be very long-running.  The experiments take from a few milliseconds to minutes or even hours each and can either terminate successfully or by running out of memory.  I catch the OutOfMemoryException to capture the latter case.  Sometimes, however, it seems that the execution does not terminate.  Neither does it run out of memory, nor does it seem to actually continue processing.

For this reason, I wanted a time limiter; basically, run a method and have it terminate either normally, with an exception or with a timeout.  Unfortunately, such functionality is not built into Java, nor does the internet seem to provide a reasonable solution.  All solutions say that you really shouldn’t do this, and instead check some variable to see if you should terminate computation.  The problem is that if you forcibly terminate a process, you leave it in an undefined state as all locks are forcibly freed (updated: cleared formulation corresponding to spand’s comment below).  Well, I don’t care about the states of my locks; when computation terminates, I drop all objects and start from scratch with the next test.

So, I made these classes for implementing time limitation:
[java] public interface ExceptionRunnable {
public void run() throws Throwable;
}

public class Future<V> {
private V value;

public V getValue() {
return value;
}

public void setValue(final V value) {
this.value = value;
}
}

public class TimeLimit implements ExceptionRunnable {
private final ExceptionRunnable r;
private final int limit;
private Throwable t;

public TimeLimit(final int limit, final ExceptionRunnable r) {
this.limit = limit;
this.r = r;
}

@SuppressWarnings(“deprecation”)
public synchronized void run() throws Throwable {
final Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
r.run();
} catch (final Throwable t) {
TimeLimit.this.t = t;
}
}
});
thread.start();
try {
thread.join(limit);
if (thread.isAlive()) {
thread.stop();
throw new InterruptedException(“Timeout”);
}
} catch (final InterruptedException e) {
if (t == null) {
t = e;
}
}
if (t != null) {
final Throwable tt = t;
t = null;
throw tt;
}
}
}
[/java] We have an interface, an helper class and the actual implementation, TimeLimit. The code is used, e.g., as:
[java] final Future<Automaton> result = new Future<Automaton>();
new TimeLimit(TIMEOUT, new ExceptionRunnable() {
@Override
public void run() throws Exception {
result.setValue(LTL2Automaton.getInstance().translateSimple(
LTL2Automaton.getInstance().parseFormula(ltl, negate), single));
}
}).run();
return result.getValue();
[/java] We start by creating an instance of Future, which will hold the result in case of successful termination. We then instantiate TimeLimit with the timeout value in milliseconds and an ExceptionRunnable, which is the same as a java.Runnable, except the run method is allowed to throw any Exception (really, Throwable). Inside the run method, we do our time-consuming task, and finally set the result of the Future we created earlier. TimeLimit itself implements ExceptionRunnable, so we start it by executing the run method. We can fainlly process the result stored in the Future, in this case we return it from another method.

If the above code snippet returns normally, it just executes, no exception is thrown, and the result is available in the Future. If an exception is raised in the long-running computation, it is just propagated, and re-thrown by the run-method of TimeLimit. Finally, if the method times out, an InterruptedException is thrown by run, and this can be handled. In a better world, I would probably have made a separate exception for this.

Also, this can be done much more elegantly using continuations, but nooooooo, you have to do it in a complicate inelegant way in Java.

4 thoughts on “Time Limitation on Method Execution in Java

  1. Just nitpicking – Stopping a thread will not leave its locks in undefined states. All monitors will be unlocked (as the ThreadDeath object travels up the stack) but that may leave objects in an undefined state.

    1. True – I’ve cleaned up the formulation. Though only locks held by entering sections protected by the synchronized keyword are freed, locks created via the java.util.concurrent.* classes are not.

      1. Well, if you use them as (which you really really should):

        lock.lock();
        try {
        // death happens here
        } finally {
        lock.unlock();
        }

        they should afaik as ThreadDeath is just a Throwable. I dont think theres any magic going on with regards to monitors.. only an exception leaving a synchronized block.

        1. Only if my code is simple. If I use those constructs instead of just synchronized, it’s typically because the locking spans multiple methods and cannot be statically determined.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.