Question

I am new to future and multithreading in java. I have a simple problem which has turned out to be complex, I have a number of threads (all have open sessions in them) which are open infinitely. Whenever one thread throws a custom exception (a timeout exception on the session), I have to interrupt all the threads and close all sessions gracefully. What I do is that I store the future objects returned by the threads (in an ArrayList) and loop through it and issue future.cancel for all when one thread throws an exception.

private static void futureCancel()
{
        for(int i=0;i<numberStreams;i++)
        {
            Future<String> future=futureList.get(i);
            try{
                future.cancel(true);
                future.get();
            }
            catch(InterruptedException e)
            {
                System.out.println("In interrupted block!");
            } catch (ExecutionException e) {
                e.printStackTrace();
            }       
        }
        return;
    }

The issue here is that I cannot add InterruptedException in my thread code due to some requirement issues and the way things work on the other side of the sessions. If I throw an InterruptedException from my callable, it does not reach the catch block specified above. Incase I add sleep in my thread (ok for testing) and handle the InterruptedException, it enters that block as soon as future.cancel is issued. What am I doing wrong?

Was it helpful?

Solution

Futuer#cancel(boolean) javadoc states

This attempt will fail if the task has already completed, has already been cancelled, or could not be cancelled for some other reason. If successful, and this task has not started when cancel is called, this task should never run. If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.

So either the ExecutorService hasn't executed the Runnable/Callable and can remove it from its queue or it has and the ExecutorService has to call Thread#interrupt() and your Runnable/Callable code has to handle it.

There's no other way through the Future interface to interrupt a thread. If your Runnable doesn't have a way to handle interrupts, then a number of things can happen. If an InterruptedException occurs, it will bubble up to the ExecutorService and be wrapped in a ExecutionException that will be thrown from Future#get(). If no InterruptedException occurs in the thread executing the Runnable, your Runnable will continue unhindered.

You should really consider changing your Runnable to handle interrupts.

OTHER TIPS

If I throw an InterruptedException from my callable, it does not reach the catch block specified above.

It won't. The InterruptedException catch block around the future.get() is when the thread that is calling the get gets interrupted -- not your Callable.

If your Callable is interrupted and throws InterruptedException then when you call get() it will enter the ExecutionException and the e.getCause() should be InterruptedException.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top