Java 如何组合3个或更多完成阶段?
如果有2个完成阶段,我可以将它们与Java 如何组合3个或更多完成阶段?,java,concurrency,java-8,Java,Concurrency,Java 8,如果有2个完成阶段,我可以将它们与然后组合方法组合: CompletionStage<A> aCompletionStage = getA(); CompletionStage<B> bCompletionStage = getB(); CompletionStage<Combined> combinedCompletionStage = aCompletionStage.thenCombine(bCompletionStage, (aData, bD
然后组合方法组合:
CompletionStage<A> aCompletionStage = getA();
CompletionStage<B> bCompletionStage = getB();
CompletionStage<Combined> combinedCompletionStage =
aCompletionStage.thenCombine(bCompletionStage, (aData, bData) -> combine(aData, bData));
是否有更好的方法组合多个CompletionStage的结果?组合多个阶段的唯一方法是使用CompletableFuture
。如果您的CompletionStage
s不是CompletableFuture
s,您仍然可以使用.toCompletableFuture()
转换它们:
尽管如此,如果你想合并更多的阶段,它的伸缩性并不好
中间解决方案(关于复杂性)可能是:
CompletionStage<Combined> combinedDataCompletionStage = aCompletionStage.thenCompose(
a -> bCompletionStage.thenCompose(b -> cCompletionStage.thenCompose(
c -> dCompletionStage.thenApply(d -> combine(a, b, c, d)))));
CompletionStage组合数据CompletionStage=a CompletionStage.then组合(
a->b完成阶段。然后撰写(b->C完成阶段。然后撰写(
c->d完成阶段。然后应用(d->combine(a,b,c,d‘‘‘)’);
它的结构更简单,但仍然不能很好地适应更多的阶段。可以缩短一点:
CompletionStage<Combined> combinedDataCompletionStage = aCompletionStage.thenCompose(
a -> bCompletionStage.thenCompose(
b -> cCompletionStage.thenCombine(dCompletionStage,
(c, d) -> combine(a, b, c, d))));
CompletionStage组合数据CompletionStage=a CompletionStage.then组合(
a->B完成阶段。然后撰写(
b->cCompletionStage。然后合并(dCompletionStage,
(c,d)->组合(a,b,c,d));
我认为您应该使用一个中间对象,而不是使用Pair
和Tuple
public R method() {
CompletableFuture<A> aFuture = getAFuture();
CompletableFuture<B> bFuture = getBFuture();
CompletableFuture<C> cFuture = getCFuture();
CompletableFuture<D> dFuture = getDFuture();
return CompletableFuture.completedFuture(new WellNamedResultHolder())
.thenCombineAsync(aFuture, WellNamedResultHolder::withAResult)
.thenCombineAsync(bFuture, WellNamedResultHolder::withBResult)
.thenCombineAsync(cFuture, WellNamedResultHolder::withCResult)
.thenCombineAsync(dFuture, WellNamedResultHolder::withDResult)
.thenApplyAsync(this::combineAllTheResults);
}
private static class WellNamedResultHolder {
private A aResult;
private B bResult;
private C cResult;
private D dResult;
// Getters
public WellNamedResultHolder withAResult(final A aResult) {
this.aResult = aResult;
return this;
}
public WellNamedResultHolder withBResult(final B bResult) {
this.bResult = bResult;
return this;
}
public WellNamedResultHolder withCResult(final C cResult) {
this.cResult = cResult;
return this;
}
public WellNamedResultHolder withDResult(final D dResult) {
this.dResult = dResult;
return this;
}
}
public R方法(){
CompletableFuture-aFuture=getAFuture();
CompletableFuture bFuture=getBFuture();
CompletableFuture cFuture=getCFuture();
CompletableFuture-dFuture=getDFuture();
返回CompletableFuture.completedFuture(新的WellNamedResultHolder())
.然后组合同步(未来,井名结果持有人::WitherResult)
.thenCombineAsync(b未来,井名结果持有者::withBResult)
.然后组合同步(C未来,井名结果持有人::withCResult)
.thenCombineAsync(数据未来,井名结果持有者::withDResult)
.然后应用同步(此::组合所有结果);
}
私有静态类WellNamedResultHolder{
私人结果;
私人B-bResult;
私人C cResult;
私人D dResult;
//吸气剂
具有最终结果的公共油井名称结果持有人(最终结果){
this.aResult=aResult;
归还这个;
}
具有bResult(最终B bResult)的公共油井名称结果持有人{
this.bResult=bResult;
归还这个;
}
公共油井名称结果持有人(最终C结果){
this.cResult=cResult;
归还这个;
}
具有dResult的公共井名dResult持有人(最终D dResult){
this.dResult=dResult;
归还这个;
}
}
结果持有者的实际形式可以明显地改变,以满足您自己的需要,给您更大的灵活性。当这些期货交易完成时,你也要对所发生的事情负责。尽管有更多的样板文件,但您得到的代码更能描述正在发生的事情(lombok可以整理)。您询问了“3个或更多”,如果您将它们作为CompletableFutures(参见其他答案)列在列表中,您可以使用以下简便方法:
private static <T> CompletableFuture<List<T>> join(List<CompletableFuture<T>> executionPromises) {
CompletableFuture<Void> joinedPromise = CompletableFuture.allOf(executionPromises.toArray(CompletableFuture[]::new));
return joinedPromise.thenApply(voit -> executionPromises.stream().map(CompletableFuture::join).collect(Collectors.toList()));
}
私有静态CompletableFuture连接(列表执行承诺){
CompletableFuture joinedPromise=CompletableFuture.allOf(executionPromises.toArray(CompletableFuture[]::new));
返回joinedPromise.thenApply(voit->executionPromises.stream().map(CompletableFuture::join).collect(Collectors.toList());
}
它将您的“未来列表”转换为“结果列表的未来”。我有一个类似的问题,但有3个以上可完成的未来,所以在回答的基础上,我制作了一个小型通用工具
public static <T, R> CompletableFuture<R> allOf(List<CompletableFuture<T>> args, Function<List<T>, R> combiner) {
final Queue<CompletableFuture<T>> queue = new LinkedList<>();
for (CompletableFuture<T> arg : args) {
queue.add(arg);
}
return aggregator(queue, new ArrayList<>(), combiner);
}
private static <T, R> CompletableFuture<R> aggregator(Queue<CompletableFuture<T>> queue, List<T> arg,
Function<List<T>, R> combiner) {
if (queue.size() == 2)
return queue.poll().thenCombine(queue.poll(), (c, d) -> {
arg.add(c);
arg.add(d);
return combiner.apply(arg);
});
return queue.poll().thenCompose(data -> {
arg.add(data);
return aggregator(queue, arg, combiner);
});
}
公共静态CompletableFuture allOf(列表参数、函数组合器){
最终队列=新建LinkedList();
用于(可完成的未来参数:参数){
queue.add(arg);
}
返回聚合器(队列、新ArrayList()、合并器);
}
专用静态CompletableFuture聚合器(队列、列表参数、,
函数组合器){
if(queue.size()==2)
返回queue.poll().thenCombine(queue.poll(),(c,d)->{
arg.添加(c);
参数添加(d);
返回合并器。应用(arg);
});
返回queue.poll().thenCompose(数据->{
参数添加(数据);
返回聚合器(队列、参数、组合器);
});
}
我认为completablefuture.allOf()函数可以帮助您
例如:(查看完整类)
列出URL=[
"https://webhook.site/1647465b-c28f-4ffe-bbfe-5d3ad95ef994",
"https://webhook.site/1647465b-c28f-4ffe-bbfe-5d3ad95ef994?a=1"
]
CompletableFuture[]期货=新的CompletableFuture[2]
对于(int i=0;i
return futures.collect{it.join()}
}.thenApply({响应->
//对结果做点什么
responses.each{println(“状态代码:+it.statusCode)}
})
可以组合(减少)任意数量的CompletableFuture
CompletionStage futA=getA();
CompletionStage futB=getB();
CompletionStage futC=getC();
流量(futA、futB、futC)
.减少((f1,f2)->f1.然后合并(f2,(d1,d2)->合并(d1,d2));
combine方法的实现将负责合并数据值(A、B和C),如果A、B和C是不同的,这可能会很棘手。您可以创建一个助手函数
combine3(
未来,未来B,未来C,
(a、b、c)->{
//我们走吧!
}).toCompletableFuture();
定义:
专用静态完成阶段组合3(
完成阶段A阶段,
完成阶段b阶段,
完成阶段cStage,
三函数f
) {
返回aStage.thenCompose(
a->b阶段。然后组合(c阶段,
(b,c)->f.应用(a,b,c));
}
接口TriF
public R method() {
CompletableFuture<A> aFuture = getAFuture();
CompletableFuture<B> bFuture = getBFuture();
CompletableFuture<C> cFuture = getCFuture();
CompletableFuture<D> dFuture = getDFuture();
return CompletableFuture.completedFuture(new WellNamedResultHolder())
.thenCombineAsync(aFuture, WellNamedResultHolder::withAResult)
.thenCombineAsync(bFuture, WellNamedResultHolder::withBResult)
.thenCombineAsync(cFuture, WellNamedResultHolder::withCResult)
.thenCombineAsync(dFuture, WellNamedResultHolder::withDResult)
.thenApplyAsync(this::combineAllTheResults);
}
private static class WellNamedResultHolder {
private A aResult;
private B bResult;
private C cResult;
private D dResult;
// Getters
public WellNamedResultHolder withAResult(final A aResult) {
this.aResult = aResult;
return this;
}
public WellNamedResultHolder withBResult(final B bResult) {
this.bResult = bResult;
return this;
}
public WellNamedResultHolder withCResult(final C cResult) {
this.cResult = cResult;
return this;
}
public WellNamedResultHolder withDResult(final D dResult) {
this.dResult = dResult;
return this;
}
}
private static <T> CompletableFuture<List<T>> join(List<CompletableFuture<T>> executionPromises) {
CompletableFuture<Void> joinedPromise = CompletableFuture.allOf(executionPromises.toArray(CompletableFuture[]::new));
return joinedPromise.thenApply(voit -> executionPromises.stream().map(CompletableFuture::join).collect(Collectors.toList()));
}
public static <T, R> CompletableFuture<R> allOf(List<CompletableFuture<T>> args, Function<List<T>, R> combiner) {
final Queue<CompletableFuture<T>> queue = new LinkedList<>();
for (CompletableFuture<T> arg : args) {
queue.add(arg);
}
return aggregator(queue, new ArrayList<>(), combiner);
}
private static <T, R> CompletableFuture<R> aggregator(Queue<CompletableFuture<T>> queue, List<T> arg,
Function<List<T>, R> combiner) {
if (queue.size() == 2)
return queue.poll().thenCombine(queue.poll(), (c, d) -> {
arg.add(c);
arg.add(d);
return combiner.apply(arg);
});
return queue.poll().thenCompose(data -> {
arg.add(data);
return aggregator(queue, arg, combiner);
});
}
List<String> urls = [
"https://webhook.site/1647465b-c28f-4ffe-bbfe-5d3ad95ef994",
"https://webhook.site/1647465b-c28f-4ffe-bbfe-5d3ad95ef994?a=1"
]
CompletableFuture<Response>[] futures = new Completablefuture[2]
for (int i = 0; i < urls.size(); i++) {
futures[i] = asyncHttpClient.prepareGet(urls[i]).execute().toCompletableFuture()
}
CompletableFuture.allOf(futures).thenApply { future ->
return futures.collect { it.join() }
}.thenApply({ responses ->
//Do something with results
responses.each { println("Status code: " + it.statusCode) }
})
CompletionStage<A> futA = getA();
CompletionStage<B> futB = getB();
CompletionStage<C> futC = getC();
Stream.of(futA, futB, futC)
.reduce((f1, f2) -> f1.thenCombine(f2, (d1, d2) -> combine(d1, d2));