并行流和 CompletableFuture 的区别

Difference between parallel stream and CompletableFuture

在 "Java 8 in action" 一书中(由 Urma、Fusco 和 Mycroft 撰写)他们强调并行流在内部使用通用的 fork 连接池,并且虽然这可以全局配置,例如使用 System.setProperty(...),不可能为单个并行流指定值。

从那以后,我看到 workaround 涉及 运行 自定义 ForkJoinPool 中的并行流。

在本书的后面,他们有一整章专门介绍 CompletableFuture,在此期间他们有一个案例研究,他们比较了使用 parallelStream 与 CompletableFuture 各自的性能。事实证明,它们的性能非常相似——它们强调了这样做的原因,因为它们都默认使用相同的公共池(因此线程数量相同)。

他们继续展示解决方案,并认为 CompletableFuture 在这种情况下更好,因为它可以配置为使用自定义执行器,线程池大小由用户选择。当他们更新解决方案以利用它时,性能得到显着提高。

这让我想到 - 如果使用上面突出显示的解决方法对并行流版本执行相同的操作,性能优势是否会相似,并且这两种方法是否会因此在性能方面再次变得相似?在这种情况下,为什么要选择 CompletableFuture 而不是并行流,因为它显然需要开发人员做更多的工作。

In this case, why would one choose the CompletableFuture over the parallel stream when it clearly takes more work on the developer's part.

恕我直言,这取决于您希望支持的界面。如果您希望支持异步 API 例如

CompletableFuture<String> downloadHttp(URL url);

在这种情况下,只有可完成的未来才有意义,因为您可能想在等待数据下来的同时做一些不相关的事情。

另一方面,parallelStream() 最适合 CPU 绑定任务,您希望每个任务都执行某些工作的一部分。即每个线程都在用不同的数据做同样的事情。正如您所说,它也更易于使用。