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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With