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?
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
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.