【问题标题】:How to call multiple completablefuture concurrently after main completable future completed主要可完成未来完成后如何同时调用多个可完成未来
【发布时间】:2020-09-08 03:54:41
【问题描述】:

下面如何增强功能,其中getB、getC、getD与A有依赖关系,需要等待A完成后才能调用。 但是我希望在 A 完成后同时调用 B C D。

感谢大家的帮助

注意:所有 dbService 都返回一个 completableFuture

CompletableFuture<List<A>> a= dbService.getA(request);
a.thenApply(a-> {
                try {
                    return dbService.getB(a);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return null;
                }
            })
            .thenAccept (result->{
                //do something with B
            });

a.thenApply(a-> {
                try {
                    return dbService.getC(a);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return null;
                }
            })
            .thenAccept (result->{
                //do something with C
            });

a.thenApply(a-> {
                try {
                    return dbService.getD(a);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return null;
                }
            })
            .thenAccept (result->{
                //do something with D
            });

【问题讨论】:

  • 使用thenApplyAsync?
  • U 表示将 all 与 applyAsync 结合?如果是这样,我如何重新传递参数 A
  • 什么意思?只需将所有三个 thenApply 替换为 thenApplyAsync
  • 我的意思是有没有将所有三个功能结合起来?谢谢
  • 您说,您希望 B、C 和 D 同时运行。所以不,你不能在一个函数中拥有这些和这些同时运行的调用。这也没有任何意义。如果要简化代码,请将 dbService 方法修复为不抛出InterruptedException,因为返回表示异步操作的对象,但声明抛出表示等待操作的异常是矛盾的.

标签: java-8 completable-future


【解决方案1】:

如果你不关心 B、C、D 的回报,那么:

CompletionStage<List<A>> aFuture = dbService.getA(request);
aFuture.whenCompleteAsync((a, ex) -> {
    if (ex != null) {
        dbService.getB(a);
        // ...
    } else {
        // ...
    }
});
aFuture.whenCompleteAsync((a, ex) -> {
    if (ex != null) {
        dbService.getC(a);
        // ...
    } else {
        // ...
    }
});
aFuture.whenCompleteAsync((a, ex) -> {
    if (ex != null) {
        dbService.getD(a);
        // ...
    } else {
        // ...
    }
});

您的程序将在dbService.getA(request) 开始后立即返回到主事件循环,甚至在它完成之前。当确实完成时,三个块中的每一个都在不同的线程上执行(由于whenComplete 排队)(而不是主线程和彼此,由于Async)。

如果你确实想用 B、C 和 D 的回报做某事,那么:

CompletionStage<List<A>> aFuture = dbService.getA(request);

CompletionStage<B> bFuture = aFuture.thenApplyAsync(a -> {
    return dbService.getB(a);
});
CompletionStage<C> cFuture = aFuture.thenApplyAsync(a -> {
    return dbService.getC(a);
});
CompletionStage<D> dFuture = aFuture.thenApplyAsync(a -> {
    return dbService.getD(a);
});

CompletionStage<Something> sFuture = bFuture.thenCompose(b -> {
    cFuture.thenCompose(c -> {
        dFuture.thenApply(d -> {
            // do something with b, c, d
            return new Something();
        });
    });
});
 

您可以使用 thenCombine 来缩短它,这就像等待 2 个期货的 thenApply

CompletionStage<List<A>> aFuture = dbService.getA(request);

CompletionStage<B> bFuture = aFuture.thenApplyAsync(a -> {
    return dbService.getB(a);
});
CompletionStage<C> cFuture = aFuture.thenApplyAsync(a -> {
    return dbService.getC(a);
});
CompletionStage<D> dFuture = aFuture.thenApplyAsync(a -> {
    return dbService.getD(a);
});

CompletionStage<Something> sFuture = bFuture.thenCompose(b -> {
    cFuture.thenCombine(dFuture, (c, d) -> {
        // do something with b, c, d
        return new Something();
    });
});

要将其扩展到任意数量的并发阶段,我喜欢像这样使用Spotify's CompletableFutures package

CompletionStage<List<A>> aFuture = dbService.getA(request);

CompletionStage<B> bFuture = aFuture.thenApplyAsync(a -> {
    return dbService.getB(a);
});
CompletionStage<C> cFuture = aFuture.thenApplyAsync(a -> {
    return dbService.getC(a);
});
CompletionStage<D> dFuture = aFuture.thenApplyAsync(a -> {
    return dbService.getD(a);
});

CompletionStage<Something> sFuture = CompletableFutures.combine((bFuture, cFuture, dFuture) -> {
    // do something with b, c, d
    return new Something();
}

【讨论】:

    猜你喜欢
    • 2015-05-10
    • 2023-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 2019-08-12
    • 2023-03-03
    • 2014-06-12
    相关资源
    最近更新 更多