【问题标题】:Asynchronous call within CallableCallable 中的异步调用
【发布时间】:2026-01-21 14:25:01
【问题描述】:

考虑以下 Java 代码(我正在使用的简化版本 - 如果有错误,那是因为我没有通过编译器运行它):

CountdownLatch latch = new CountdownLatch(collection.size());

for(Whatever thing : collection){

    provider.doWork(thing, result -> {
        process(result);
        latch.countDown();
    };
}

try {
    latch.await();
} catch (InterruptedException ignore) {}

doMoreWork();

所以我运行了一些异步任务,并等待它们全部完成后再继续。现在我在一个列表中累积异步任务的结果。这行得通,很好,但我正在研究是否有使用 Futures 或类似东西的更清洁的实现。问题是异步调用。一个 Callable 应该返回其工作的结果,但这项工作的结果要等到以后才能知道。将doWork 重写为同步是不值得的。我应该不理会这个,还是那里有选择?我的兴趣部分是对更好的代码,但部分是为了更多地了解并发选项。如果重要的话,这是在 Android 应用中。

【问题讨论】:

  • 您能否尝试使用带有 supplyAsync 方法的 completableFuture 对象。它是 java 8 的一个概念,它将帮助您解决您的目的。
  • 谢谢,现在开始阅读。如果有人想使用该类提供一些代码,那将是受欢迎的。
  • 不幸的是,supplyAsync 仅在 Android API 级别 24 中可用,我无法将我的最低 SDK 级别设置得那么高 - 会留下太多用户。
  • 真的取决于你的约束是什么。如果运行它的方法阻塞是可以的,那么不要管它 - 代码很好。如果该方法不打算阻塞,您可以考虑将其重写为该方法返回未来或可观察的形式,或者采用返回累积结果的回调。但是,这也需要在调用方站点上进行更改。
  • 阻塞也好,在后台线程中。感谢您的意见。

标签: java android concurrency java.util.concurrent


【解决方案1】:

这是一种使用 ExecutorService 和 Future 的方法,未在 android 上测试,但在 1 级 api 上都可用:

ExecutorService executor = Executors.newFixedThreadPool(10);
List<Future<String>> pending = new ArrayList<Future<String>>();
for(Whatever thing : collection) {
    Future<String> future = executor.submit(new Callable<String>() {
        public String call() throws Exception {
            return doWork();
        }
    });
    pending.add(future);
}
for (Future<String> result : pending) {
    System.out.println("Your result ASAP:" + result.get());
}
executor.shutdown();

一旦当前项目完成,它将按照提交的顺序返回。

【讨论】: