Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write interruptable methods

I have a method which, conceptually, looks something like:

Object f(Object o1) {
    Object o2 = longProcess1(o1);
    Object o3 = longProcess2(o2);
    return longProcess3(o3);
}

Where the processes themselves might also be compound:

Object longProcess1(Object o1) {
    Object o2 = longSubProcess1(o1);
    return longSubProcess2(o2);
}

And so forth, with the different processes potentially sitting in different modules. Most of the processes are long because they are computationally expensive, not IO-bound.

So far so good, but now I want f as a whole to be interruptable. The recommended Java way to do that is to periodically check for the interrupted flag with Thread.interrupted(). It's pretty straightforward, but it can quickly become cumbersome if I need to change my methods to something like:

Object f(Object o1) {
    Object o2 = longProcess1(o1);
    if (Thread.interrupted()) throw new InterruptedException();
    Object o3 = longProcess2(o2);
    if (Thread.interrupted()) throw new InterruptedException();
    return longProcess3(o3);
}

Object longProcess1(Object o1) {
    Object o2 = longSubProcess1(o1);
    if (Thread.interrupted()) throw new InterruptedException();
    return longSubProcess2(o2);
}

...

Now, I do understand the rational for working like that - it allows me to better control when the InterruptedException (for example) will be thrown, avoiding leaving objects in inconsistent states - but I am curious to know if there's a more elegant way of doing that*.

* In Java, not AspectJ, which I guess is very appropriate here but I'm stuck with Java.

like image 570
Oak Avatar asked Jul 05 '10 10:07

Oak


People also ask

What is InterruptedException explain it with a small example?

An InterruptedException is thrown when a thread is interrupted while it's waiting, sleeping, or otherwise occupied. In other words, some code has called the interrupt() method on our thread. It's a checked exception, and many blocking operations in Java can throw it.

What is interrupt method?

interrupt() method: If any thread is in sleeping or waiting for a state then using the interrupt() method, we can interrupt the execution of that thread by showing InterruptedException. A thread that is in the sleeping or waiting state can be interrupted with the help of the interrupt() method of Thread class.

What does thread currentThread () interrupt () do?

By calling Thread. currentThread(). interrupt() , you set the interrupt flag of the thread, so higher-level interrupt handlers will notice it and can handle it appropriately.


1 Answers

You could use an interface and a Dynamic proxy:

public class Wrapper {
    public static <T> T wrap(Class<T> intf, final T impl) {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        Object proxy = Proxy.newProxyInstance(cl, new Class<?>[] {intf},
                new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                if (Thread.interrupted()) {
                    throw new InterruptedException();
                }
                return method.invoke(impl, args);
            }
        });
        return intf.cast(proxy);
    }
}

interface Processes {
    Object longProcess1(Object o);
    ...
}

public class ProcessesImpl implement Processes {
    Processes self = Wrapper.wrap(Processes.class, this);

    public Object f(Object o1) {
        Object o2 = self.longProcess1(o1);
        Object o3 = self.longProcess2(o2);
        return self.longProcess3(o3);
    }

    public Object longProcess1(Object o1) {
        Object o2 = self.longSubProcess1(o1);
        return self.longSubProcess2(o2);
    }

    ....
}
like image 99
Maurice Perry Avatar answered Oct 05 '22 03:10

Maurice Perry