Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Continue when one future task has expected result

I have 3 FutureTask<T> Objects. I want that they are processed asynchronously. However, as soon as one of the FutureTasks' get() methods doesn't return null I want to continue i.e my method (wrapper) returns and doesn't wait until the other two FutureTasks are processed. I thought about something like:

private File wrapper(final File file) {
    ExecutorService executors = Executors.newCachedThreadPool();
    File returnFile;
    FutureTask<File> normal= ...
    FutureTask<File> medium=...     
    FutureTask<File> huge=...

    executors.execute(normal);
    executors.execute(medium);
    executors.execute(huge);
    try {
        if((returnFile=normal.get()) != null || 
           (returnFile=medium.get()) != null ||  
           (returnFile=huge.get()) != null)

            return returnFile;

    } catch(ExecutionException | InterruptedException e) { }
}

I'm not sure how to capture the exceptions (thrown by the get()) in a proper way because I assume they will be thrown since I just return without waiting for the other two tasks to be completed. Moreover I've doubts that the code will work like intended. I feel that I'm close to the solution but missing something.

like image 667
Brenne Avatar asked Jul 20 '15 12:07

Brenne


People also ask

How can you make sure future task done?

A Future interface provides methods to check if the computation is complete, to wait for its completion and to retrieve the results of the computation. The result is retrieved using Future's get() method when the computation has completed, and it blocks until it is completed.

How does Future cancel work?

cancel() will cancel any queued task or will call Thread. interrupt() on your thread if already running. It's your code's responsibility is to be ready for any interruptions.

Which method of Executorservice is called to check that all tasks are complete following shutdown?

When using an Executor, we can shut it down by calling the shutdown() or shutdownNow() methods. Although, it won't wait until all threads stop executing. Waiting for existing threads to complete their execution can be achieved by using the awaitTermination() method.


1 Answers

May I suggest to check for FutureTask::isDone?

Would be something like this then:

while(true) {
    if (normal.isDone()) {
        return normal.get();
    }
    if (medium.isDone()) {
        return medium.get();
    }
    if (huge.isDone()) {
        return huge.get();
    }
}

EDIT: You could cancel the other tasks as soon as you have one result at hand.

Using FutureTask::get is not what you look for as it would most likely always return the result of normal.get() because the documentation already states that:

Waits if necessary for the computation to complete, and then retrieves its result.

To clarify the above: If you use FutureTask::get the first FutureTask you call get on will most likely block and wait until a result is available to return.

EDIT2:

Wrap that loop into a new Runnable, executed by the ExecutorService, passing the first result available to another method or implement a Callback and there's no more busy waiting.

like image 166
Oliver Avatar answered Sep 23 '22 11:09

Oliver