Guava Futures Wait for Callback

12,401

Solution 1

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.

Solution 2

How about if you create another future for each callback and make sure that it will be completed inside the callback.

// create "callback" future here
futures.add(callbackFuture);

Futures.addCallback(future, new FutureCallback<Object>() {

  @Override
  public void onFailure(Throwable t) {
    t.printStackTrace();
    // do something with callbackFuture
  }

  @Override
  public void onSuccess(Object x) {
    try {Thread.sleep((Integer) x * 10);} catch (Exception e) {}

    System.out.println(x);
    // do something with callbackFuture
  }
});
Share:
12,401
vinoths
Author by

vinoths

Updated on June 25, 2022

Comments

  • vinoths
    vinoths almost 2 years

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