我有一个 future 列表,每个 future 完成后,我都有一个应该执行的回调。

我正在使用Futures.successfulAsList检查是否所有 future 都已完成。但是,这没有考虑回调的完成。

有什么方法可以确保回调完成吗?

代替回调,我可以使用Futures.transform包装到另一个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");

最佳答案

如果您只想阻塞直到提交的N个任务的回调全部完成,则可以创建一个CountDownLatch为N的 count 。然后在每个回调完成时(无论成功还是失败)调用countDown()并对其进行await()在您要阻止的位置。

另外,您可以像在回答中一样做一些事情,但不必使用ListenableFutureTask<Void>和无操作Runnable,而只需使用SettableFuture<Void>并在完成时调用set(null)即可。

关于java - Guava future 等待回调,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17671957/

10-11 19:18