为了账号安全,请及时绑定邮箱和手机立即绑定

等待未来的清单

等待未来的清单

偶然的你 2019-12-12 14:16:30
我有一种返回List期货的方法List<Future<O>> futures = getFutures();现在,我要等待,直到所有期货都成功完成处理,或者所有由期货返回输出的任务都引发异常。即使一项任务引发异常,也没有必要等待其他期货。简单的方法是wait() {   For(Future f : futures) {     try {       f.get();     } catch(Exception e) {       //TODO catch specific exception       // this future threw exception , means somone could not do its task       return;     }   }}但是这里的问题是,例如,如果第4个期货抛出异常,那么我将不必要地等待前3个期货可用。如何解决呢?会以任何方式倒计时闩锁帮助吗?我无法使用Future,isDone因为Java文档说boolean isDone()Returns true if this task completed. Completion may be due to normal termination, an exception, or cancellation -- in all of these cases, this method will return true.
查看完整描述

3 回答

?
动漫人物

TA贡献1815条经验 获得超10个赞

如果您使用的是Java 8,则可以使用CompletableFuture和CompletableFuture.allOf轻松完成此操作,它们仅在完成所有提供的CompletableFutures之后才应用回调。


// Waits for *all* futures to complete and returns a list of results.

// If *any* future completes exceptionally then the resulting future will also complete exceptionally.


public static <T> CompletableFuture<List<T>> all(List<CompletableFuture<T>> futures) {

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


    return CompletableFuture.allOf(cfs)

            .thenApply(ignored -> futures.stream()

                                    .map(CompletableFuture::join)

                                    .collect(Collectors.toList())

            );

}


查看完整回答
反对 回复 2019-12-12
?
三国纷争

TA贡献1804条经验 获得超7个赞

您可以使用ExecutorCompletionService。该文档甚至提供了一个具体用例的示例:


相反,假设您想使用任务集的第一个非空结果,忽略遇到异常的任何结果,并在第一个任务就绪时取消所有其他任务:


void solve(Executor e, Collection<Callable<Result>> solvers) throws InterruptedException {

    CompletionService<Result> ecs = new ExecutorCompletionService<Result>(e);

    int n = solvers.size();

    List<Future<Result>> futures = new ArrayList<Future<Result>>(n);

    Result result = null;

    try {

        for (Callable<Result> s : solvers)

            futures.add(ecs.submit(s));

        for (int i = 0; i < n; ++i) {

            try {

                Result r = ecs.take().get();

                if (r != null) {

                    result = r;

                    break;

                }

            } catch (ExecutionException ignore) {

            }

        }

    } finally {

        for (Future<Result> f : futures)

            f.cancel(true);

    }


    if (result != null)

        use(result);

}

这里要注意的重要一点是ecs.take()将获得第一个完成的任务,而不仅仅是第一个提交的任务。因此,您应该按照完成执行(或引发异常)的顺序获取它们。

查看完整回答
反对 回复 2019-12-12
  • 3 回答
  • 0 关注
  • 322 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信