Guava Futures Wait for Callback

future, guava, java

Solution

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.

Problem

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"); ```

Original source