I have a list of futures and on completion of each future, I have a callback that should get executed.
I am using Futures.successfulAsList to check if all the futures have completed. However, this doesn't take into account the completion of callback.
Is there a way I can ensure the callback is completed?
Instead of Callback, I could use Futures.transform to wrap into another Future and check for completion of that. However, with this, I don't get access to runtime exception thrown in the wrapped future.
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(20));
List<ListenableFuture<Object>> futures = new ArrayList<>();
for (int i = 1; i <= 20; i++) {
final int x = i * 100;
ListenableFuture<Object> future = service.submit(new Callable() {
@Override
public Object call() throws Exception {
Thread.sleep(10000 / x);
return x;
}
});
futures.add(future);
Futures.addCallback(future, new FutureCallback<Object>() {
@Override
public void onFailure(Throwable t) {
t.printStackTrace();
}
@Override
public void onSuccess(Object x) {
try {Thread.sleep((Integer) x * 10);} catch (Exception e) {}
System.out.println(x);
}
});
}
ListenableFuture<List<Object>> listFuture = Futures
.successfulAsList(futures);
System.out.println("Waiting...");
System.out.println(listFuture.get());
System.out.println("Done");
addCallBack(): addCallback(ListenableFuture<V> future, FutureCallback<? super V> callback) Registers separate success and failure callbacks to be run when the Future's computation is complete or, if the computation is already complete, immediately.
One lacking feature when using java. util. concurrent. Future is the ability to add listeners to run on completion, which is a common feature provided by most popular asynchronous frameworks.
If you just want to block until the callbacks for the N tasks you submit have all completed, you could create a CountDownLatch
with a count
of N. Then just call countDown()
on it when each callback completes (whether it succeeds or fails) and await()
it at the point you want to block.
Alternatively, you could do something like you did in your answer, but rather than using a ListenableFutureTask<Void>
and a no-op Runnable
, just use a SettableFuture<Void>
instead and call set(null)
on it on completion.
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