当前位置: 首页 > 知识库问答 >
问题:

等待列表中的每个未来完成[关闭]

年凯康
2023-03-14

想改进这个问题吗 通过编辑这篇文章,更新问题,以便用事实和引文来回答。

我调用一个方法,该方法为列表中的每个元素返回一次未来

返回Future的方法是库代码,我无法控制该代码的运行方式,我所拥有的只是Future

我想等待所有Future完成(成功或失败),然后再继续。

有没有比这更好的方法:

List<Principal> users = new ArrayList<>();
// Fill users
List<Future<UserRecord>> futures = getAllTheFutures(users);
List<UserRecord> results = new ArrayList<>(futures.size());
boolean[] taskCompleted = new boolean[futures.size()];
for (int j = 0; j < taskCompleted.length; j++) {
    taskCompleted[j] = false;
}
do {
    for (int i = 0; i < futures.size(); i++) {
        if (!taskCompleted[i]) {
            try {
                results.add(i, futures.get(i).get(20, TimeUnit.MILLISECONDS));
                taskCompleted[i] = true;
            } catch (TimeoutException e) {
                // Do nothing
            } catch (InterruptedException | ExecutionException e) {
                // Handle appropriately, then...
                taskCompleted[i] = true;
            }
        }
    }
} while (allNotCompleted(taskCompleted));

对于好奇的人:

private boolean allNotCompleted(boolean[] completed) {
    for (boolean b : completed) {
        if (!b)
            return true;
    }
    return false;
}

与这个等待未来列表的答案不同,我无法控制创建未来的代码。

共有2个答案

苏骏
2023-03-14

您可以简单地做一个简化列表;从列表中删除成功的响应并迭代直到为空。

List<Principal> users = // fill users
List<Future<UserRecord>> futures = getAllTheFutures(users);
List<UserRecord> results = new ArrayList<>();

for (int i = 0; i < futures.size(); i++) {
        try {
            results.add(futures.get(i).get(<how long you want before your application throws exception>));

        }
        catch (InterruptedException | ExecutionException e) {
            // Handle appropriately, results.add(null) or just leave it out
        }
        catch (TimeoutException timeoutEx) {
            // If the Future retrieval timed out you can handle here
        }

    }
}

由于您的目的是在继续之前收集一组作业,因此在这种情况下,等待线程索引X的返回将导致(大致)最后返回的线程的时间开销。

或者,如果计划在任何线程失败时中止该集中的所有线程,则可以使用Java 8 CompletableFuture

CompletableFuture[] cfs = futures.toArray(new CompletableFuture[futures.size()]);

    return CompletableFuture.allOf(cfs)
            .thenApply(() -> futures.stream()
                                    .map(CompletableFuture::join)
                                    .collect(Collectors.toList())
            );
  • Kayaman简化了代码库
苏翰学
2023-03-14

您的代码可以简化很多。除非您有问题中未指定的要求,否则可以按照以下方式编写等效版本。

List<Principal> users = // fill users
List<Future<UserRecord>> futures = getAllTheFutures(users);
List<UserRecord> results = new ArrayList<>();

for (int i = 0; i < futures.size(); i++) {
        try {
            results.add(futures.get(i).get());
        } catch (InterruptedException | ExecutionException e) {
            // Handle appropriately, results.add(null) or just leave it out
        }
    }
}
 类似资料:
  • 我要做的是异步计算树结构的深度,我将有树的第一层,我想启动一个异步线程来分别计算每个节点的深度。 在计算过程中,树中显然可能有一个分叉,在这一点上,我想踢一个额外的线程来计算那个分支。 我已经得到了这个工作,但我需要做一些整理逻辑,当所有这些未来完成。但我对这一过程中产生的额外的可完成的未来感到困扰。 我会用什么方法来保存所有开始的CompletableFutures+那些动态创建的,并且在执行任

  • 是否有一种方法可以在不阻塞事件循环的情况下等待一个未来完成? 我知道这个错误通常意味着什么,但我不知道在这种情况下...我试图在谷歌上搜索它,但没有找到任何关于将哪份清单放在哪里的明确解释。和以前一样,除非是强制性的,我更喜欢一次学一件事。 那么,回到这个问题:“基本”Vert.x是否有一种方法可以在事件循环不受干扰的情况下等待未来?

  • 问题内容: 我有一个调用一些不检查线程中断的代码。调用之后,该方法将立即抛出(如预期的那样)。但是,由于后台任务的代码从不检查其线程是否被中断,因此它很乐意继续执行。 是否有等待后台任务 实际 完成的标准方法?我希望显示“正在取消…”消息或某种类似的内容,直到任务终止为止。(我确信如果有必要,我总是可以在worker类中使用一个标志来完成此操作,只需寻找其他解决方案即可。) 问题答案: 我玩了一点

  • 是否有一种方法可以尝试等待一段时间,然后返回不同的结果,而不取消超时后的未来? 我有一个服务(我们称之为),它跑出去做自己的事情。它返回一个结果: 我愿意[阻止并]等待它一小段时间(比方说2秒)。如果它没有完成,我希望返回一个不同的结果,但我希望服务继续做它自己的事情。然后查询服务是否完成(例如,通过websockets或其他方式)将是客户端的工作。 即。我们有以下几个案例: 花费%1 s并完成其

  • 我想运行相同类型的任务(工作线程),但一次不超过一定数量的任务。当任务完成时,其结果是新任务的输入,然后可以启动该任务。 有没有好的方法可以在C 11中使用异步/未来范式来实现这一点? 乍一看,它看起来很简单,你只是生成多个任务: 然后,运行以获取任务的异步结果。 然而,这里的问题是,未来的对象必须存储在某种队列中并一个接一个地等待。但是,可以一遍又一遍地迭代未来的对象,检查它们中的任何一个是否准

  • 我希望像下面这样的代码可以等待这两种未来,但是没有。 我以为< code>seq.onComplete会在完成自身之前等待它们全部完成,但事实并非如此;它会导致: 在scala.concurrent.Future的源代码中有点难以遵循,我想知道如何实现等待(动态大小的)序列的所有原始未来的并行,或者这里可能有什么问题。 编辑:相关问题:https://worldbuilding.stackexch