ExecutorService.submit(Task) vs CompletableFuture.supplyAsync(Task, Executor)

为了并行或异步运行一些东西,我可以使用ExperidorService:或CompletableFuture Api:(假设我在两种情况下都使用相同的执行器)<T> Future<T> submit(Runnable task, T result);static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor);

除了返回类型 vs. 有什么显著的区别吗?或者什么时候使用什么?FutureCompletableFuture

如果我使用默认的API(没有执行器的方法)有什么区别?CompletableFutureExecutor


答案 1

除了返回类型Future与CompletableFuture之外,还有任何显着的差异。或者什么时候使用什么?

这真的很简单。当您希望执行线程等待异步计算响应时,可以使用 。这方面的一个例子是并行合并/排序。异步向左排序,同步向右排序,在左侧等待完成 (),合并结果。Futurefuture.get()

当您希望执行某些操作时,可以使用 a,其结果在完成后从执行的线程异步执行。例如:我想异步进行一些计算,当我计算时,将结果写入某个系统。然后,请求线程可能不需要等待结果。CompleteableFuture

您可以在单个 Future 可执行文件中模拟上述示例,但它提供了更流畅的界面和更好的错误处理。CompletableFuture

这真的取决于你想做什么。

如果我使用CompletableFutureApi与默认的执行器(没有执行器的方法)有什么区别?

它将委托系统上 CPU 数量的默认大小。如果您正在执行 IO 密集型操作(读取和写入文件系统),则应以不同的方式定义线程池。ForkJoin.commonPool()

如果是 CPU 密集型,则使用 commonPool 最有意义。


答案 2

CompletableFuture具有丰富的功能,例如链接多个期货,组合期货,在期货执行后执行某些操作(同步和异步)等。

然而,CompletableFuture在性能方面与Future没有什么不同。即使将ComppletableFuture的多个实例组合在一起(最终使用.thenCombine和.join),除非我们调用.get方法,否则它们都不会被执行,并且在此期间,调用线程将被阻塞。我觉得在表现方面,这并不比未来好。

请让我知道,如果我在这里错过了性能的某些方面。


推荐