在Java 8中,有两种启动异步计算的方法 - CompletableFuture
和ForkJoinTask
。它们看起来都非常相似——CompletableFuture
的内部类甚至扩展ForkJoinTask
。
有理由使用一个而不是另一个吗?
我可以看到的一个关键区别是,CompletableFuture.join
方法只是阻止直到未来完成(waitingGet
只是使用ManagedBlocker
旋转(,而ForkJoinTask.join
可以从队列中窃取工作以帮助您完成的任务。
比一个或另一个有好处吗?
它们是两回事,ForkJoinTask
是可以提交给ForkJoinPool
的任务,CompletableFuture
是可以与任何Executor
一起使用的承诺,执行者不需要是ForkJoinPool
,
但是,如果您不指定任何公共ForkJoinPool
,则确实是默认值,例如:
CompletableFuture.supplyAsync(()-> supplier);
如果您不通过Executor
,则使用ForkJoinPool
。还有另一种overload
需要Executor
.
CompletableFuture.supplyAsync(()-> supplier,executor);
Async
,这是一个static
类,CompletableFuture
扩展了ForkJoinTask<Void>
,但它不需要是一个ForkJoinTask
,从Async
的文档
/** 基类可以充当 FJ 或普通可运行 */
abstract static class Async extends ForkJoinTask<Void>
implements Runnable, AsynchronousCompletionTask
它也可以是一个Runnable
和一个AsynchronousCompletionTask
附带说明:ForkJoinTask
、ForkJoinPool
、ForkJoin...
类是在 1.7 而不是 1.8 中添加
我想说的是,当您有一个大任务并希望将其拆分为在几个子任务中并行运行时,更推荐使用 ForkJoinTask
。ForkJoin
框架使用工作窃取算法,该算法将有效利用线程。另一方面,CompletableFutures
更适合响应式编程模型,在该模型中,您可以以同步或异步方式创建执行管道,并使用执行程序服务的线程池更好地控制线程。