ForkJoinTask vs CompletableFuture

2019-06-16 10:23发布

问题:

In Java 8 there are two ways of starting asynchronous computations - CompletableFuture and ForkJoinTask. They both seem fairly similar - the inner classes of CompletableFuture even extend ForkJoinTask.

Is there a reason to use one over the other?

One key difference that I can see is that the CompletableFuture.join method simply blocks until the future is complete (waitingGet just spins using a ManagedBlocker), whereas a ForkJoinTask.join can steal work off the queue to help the task you're joining on to complete.

Is there a benefit over one or the other?

回答1:

They are two different things, ForkJoinTask is a task that can be submitted to a ForkJoinPool, CompletableFuture is a promise that can work with any Executor and the executor doesn't need to be the ForkJoinPool,

It is true however that the common ForkJoinPool is the default if you don't specify any, for ex:

CompletableFuture.supplyAsync(()-> supplier);

uses the ForkJoinPool if you don't pass an Executor. There is another overload that takes an Executor.

CompletableFuture.supplyAsync(()-> supplier,executor);

Async ,which is a static class in CompletableFuture extends ForkJoinTask<Void>, but it doesn't need to be a ForkJoinTask, from the docs of Async

/** Base class can act as either FJ or plain Runnable */

abstract static class Async extends ForkJoinTask<Void>
    implements Runnable, AsynchronousCompletionTask 

It can also a Runnable and a AsynchronousCompletionTask

Just on side note: ForkJoinTask, ForkJoinPool, ForkJoin... classes were added in 1.7 and not 1.8



回答2:

I'd say that the ForkJoinTask is more recommended when you have a big task and want to split it to run in parallel in several sub tasks. The ForkJoin framework uses the work stealing algorithm which will make an efficient use of the threads. On the other hand, CompletableFutures are more appropriate for a Reactive programming model, where you can create pipelines of execution in a sync or async fashion, and have a better control of the threads by using the thread pools of the Executor Service.