Continue when one of the future challenges is expected.

I have 3 FutureTask<T> Objects. I want them to be processed asynchronously. However, as soon as one of the get() methods of FutureTasks does not return null , I want to continue, that is, my method (shell) will return and do not wait until the other two future tasks are processed. I thought of 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 am not sure how to write exceptions correctly (thrown by get () method), because I assume that they will be discarded as soon as I just return, without waiting for the completion of two other tasks. Moreover, I doubt that the code will work as intended. I feel like I'm close to a solution, but something is missing.

+6
source share
2 answers

May I suggest checking for FutureTask :: isDone?

There will be something like this:

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

EDIT: You can cancel other tasks as soon as you have one result.

Using FutureTask :: get is not what you are looking for, as it will most likely always return the result of normal.get (), as the documentation already states that:

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

To clarify the above: If you use FutureTask :: get the first FutureTask that you call, it will most likely block and wait for the result to return.

EDIT2:

Wrap this loop in a new Runnable executed by ExecutorService, passing the first result available to another method, or implement a callback and the wait will not be taken.

+1
source

I had an idea to create it using BlockingQueue. You expand your tasks by executing the method of sending results to BlockinQueue and, as soon as the client receives the first result, it cancels other tasks. On the other hand, experts suggest using ExecutorCompletionService . It seems to serialize the results itself and has all the relevant examples .

0
source

All Articles