nano7 nano7 - 4 months ago 26
Java Question

Java: ExecutorService with Callables: Timeout: future.get() leads to direct break of program

I use the ExecutorService in Java and I noticed a behaviour I dont understand.
I use Callable and when I invoke my threads (classes that implement Callable) I set a timeout. Then I wait for the result with

future.get()
and after I wanted to check with
future.isDone()
if a timeout occurs during executing the tasks.

As I read in the documentation for invokeAll with timeout:
returns a list of Futures representing the tasks, in the same sequential order as produced by the iterator for the given task list. If the operation did not time out, each task will have completed. If it did time out, some of these tasks will not have completed.


So I thought I would get a list of Future results in both cases, if a timeout occurs and if it does not.

What now happens is the following: When a timeout occurs, the code does not go on after
future.get()
and I dont ever get to the point where I could check if a timeout occurs with
future.isDone()
. I dont catch any exception, Im directly leaded to the finally block in my code, which I really dont understand.

here is a snippet of my code:

try {
// start all Threads
results = pool.invokeAll(threads, 3, TimeUnit.SECONDS);

for (Future<String> future : results)
{
try
{
// this method blocks until it receives the result, unless there is a
// timeout set.
final String rs = future.get();

if (future.isDone())
{
// if future.isDone() = true, a timeout did not occur.
// do something
}
else
{
// timeout
// log it and do something
break;
}
}
catch (ExecutionException e)
{
// log messages and break, this is a snippet!
}
catch (InterruptedException ex)
{
// log message and break, this is a snippet!
}
}

}
catch (InterruptedException ex)
{
// log message, this is a snippet!
}
finally
{
// when a timeout occurs, the code jumps from future.get() directly to this point!
}


Might somebody explain me, why I am not able to reach
future.isDone()
and what I should change to be able to recognize timeouts?

Thank you!

Answer

You are not catching CancellationException, which is very likely being thrown after calling get. Note that this exception extends RuntimeException and the compiler won't warn you to catch it.

Reading the docs for invokeAll:

Executes the given tasks, returning a list of Futures holding their status and results when all complete or the timeout expires, whichever happens first. Future.isDone() is true for each element of the returned list. Upon return, tasks that have not completed are cancelled.