你的主句是:
CompletableFuture<String> allGen = loadFile1().thenApply(params1 -> {
…
});
所以指定的函数应该返回一个`String`。但是你的代码试图返回一个`CompletableFuture<String>`,因为`Stream.of(gen1, gen2).map(CompletableFuture::join).collect(joining(","))`产生了一个`String`,而你正在在`return CompletableFuture.allOf(gen1, gen2).thenApply(r -> …);`中使用这个表达式。
在泛型代码中,编译器错误消息通常是非常无用的。
最简单的解决方法(改动最小)是使用`thenCompose`而不是`thenApply`,允许函数返回一个`CompletableFuture`。
CompletableFuture<String> allGen = loadFile1().thenCompose(params1 -> {
CompletableFuture<String> gen1 = loadFile2().thenApply(params2 -> {
return generateResultFile1(params1, params2);
});
CompletableFuture<String> gen2 = loadFile3().thenApply(params3 -> {
return generateResultFile2(params1, params3);
});
return CompletableFuture.allOf(gen1, gen2)
.thenApply(r -> Stream.of(gen1, gen2)
.map(CompletableFuture::join).collect(joining(",")));
});
然而,有利用简化语法的机会。
CompletableFuture<String> allGen = loadFile1().thenCompose(params1 -> {
CompletableFuture<String> gen1 = loadFile2()
.thenApply(params2 -> generateResultFile1(params1, params2));
CompletableFuture<String> gen2 = loadFile3()
.thenApply(params3 -> generateResultFile2(params1, params3));
return CompletableFuture.allOf(gen1, gen2)
.thenApply(r -> Stream.of(gen1, gen2)
.map(CompletableFuture::join).collect(joining(",")));
});
如果代码总是将恰好两个结果合并,那么可以使用更简单的方法:
CompletableFuture<String> allGen = loadFile1().thenCompose(params1 ->
loadFile2().thenApply(params2 -> generateResultFile1(params1, params2))
.thenCombine(
loadFile3().thenApply(params3 -> generateResultFile2(params1, params3)),
(s1, s2) -> String.join(",", s1, s2))
);
尽管有不同的嵌套形式,
loadFile2().thenApply(…)
和
loadFile3().thenApply(…)
仍然是两个独立的操作,只有最终的
(s1, s2) -> String.join(",", s1, s2)
依赖于两者。
如果想使这更加清晰明了,请保留本地变量。
CompletableFuture<String> allGen = loadFile1().thenCompose(params1 -> {
CompletableFuture<String> gen1
= loadFile2().thenApply(params2 -> generateResultFile1(params1, params2));
CompletableFuture<String> gen2
= loadFile3().thenApply(params3 -> generateResultFile2(params1, params3));
return gen1.thenCombine(gen2, (s1, s2) -> s1 + "," + s2);
});
如上例所示,您也可以将String.join(",", s1, s2)
替换为s1 + "," + s2
。后者会稍微更加高效,但由于它不太可能在整体性能方面占主导地位,因此这更多是一种口味问题。
gen1.thenCombine(gen2
会使得gen1
和gen2
并行运行吗? - CristianoallOf
一样,这对它们的完成没有任何影响。决定它们如何完成的是loadFile2()
和loadFile3()
方法以及它们创建future的方式。allOf
和thenCombine
(以及所有其他链接操作)两种方法都只会创建一个新的future,当传入的futures已经完成时,它才会被完成。如果您想确保generateResultFile1
和generateResultFile2
在任何情况下都并行运行,则必须将thenApply
替换为thenApplyAsync
。 - Holgerreturn CompletableFuture.supplyAsync()
。我将在它们上面添加日志,以便查看使用哪些线程来执行它们。 - Cristiano