nano7
nano7

Reputation: 2493

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!

Upvotes: 2

Views: 5715

Answers (3)

Ashish Thukral
Ashish Thukral

Reputation: 1485

Use isCancelled. If false, that means no timeout. then you can call get() and catch executionException if task did not timeout but had an exception due to any other reason, like nullpointer, assert, etc

Upvotes: 0

Tudor
Tudor

Reputation: 62439

I'm not sure you are using invokeAll correctly. The javadoc says:

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.

So what is the point of calling isDone since for all the Futures returned isDone is true?

Upvotes: 3

Mister Smith
Mister Smith

Reputation: 28168

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.

Upvotes: 7

Related Questions