Suppose we have two executors, 1 and 2.
We can configure which executor to use when doing
CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(()-> {return 1;}, executor1) //executor1
CompletableFuture<Integer> cf2 = CompletableFuture.supplyAsync(()-> {return 2;}, executor1) //executor1
CompletableFuture<Integer> cf3 = CompletableFuture.supplyAsync(()-> {return 3;}, executor2) //executor2
but which thread executor uses CompletableFuture static method allOf?
CompletableFuture.allOf(cf1, cf2, cf3)
Thanks!
It returns a new CompletableFuture object when all of the specified CompletableFutures are complete. If any of the specified CompletableFutures are complete with an exception, the resulting CompletableFuture does as well, with a CompletionException as the cause.
It just provides a get() method which blocks until the result is available to the main thread. Ultimately, it restricts users from applying any further action on the result. You can create an asynchronous workflow with CompletableFuture. It allows chaining multiple APIs, sending ones to result to another.
static <U> CompletableFuture<U> supplyAsync (Supplier<U> s): It accepts input as Supplier and returns a new CompletableFuture with value obtained by invoking the Supplier. The difference between runAsync() and supplyAsync() is that the former returns a Void while supplyAsync() returns a value obtained by the Supplier.
defaultExecutor() is an instance method of the CompletableFuture class. This method is used to get the default pool of threads that are used by the async methods of the CompletableFuture class when a custom executor is not specified. The defaultExecutor method is defined in the CompletableFuture class.
The answer of Ivan Gammel is not exact.
There is indeed no executor associated with the CompletableFuture
returned by allOf()
, as in fact, there isn't ever an executor associated with any CompletableFuture
.
A task is associated with an executor, as it is running inside of it, but the association is inverse: the executor has a list of tasks to execute.
A task can also be associated with a CompletableFuture
, which it will complete when the task finishes. The CompletableFuture
itself does not keep a reference to the task or executor that were used for its creation. It may however keep references to tasks and optionally executors used in dependent stages.
The CompletableFuture
returned by allOf()
will be completed by a task, which is a dependant stage of the original CompletableFuture
s. In your example, this task can be executed by:
executor1
, if the third task finished first;executor2
, if the 2 first tasks finished before the third one; orallOf()
.This can be seen by adding a dependent thenRun()
stage to the allOf()
call:
public class CompletableFutureAllOfCompletion {
private ExecutorService executor1 = Executors.newFixedThreadPool(2);
private ExecutorService executor2 = Executors.newFixedThreadPool(2);
private Random random = new Random();
public static void main(String[] args) {
new CompletableFutureAllOfCompletion().run();
}
public void run() {
CompletableFuture<Integer> cf1 = supplyAsync(this::randomSleepAndReturn, executor1);
CompletableFuture<Integer> cf2 = supplyAsync(this::randomSleepAndReturn, executor1);
CompletableFuture<Integer> cf3 = supplyAsync(this::randomSleepAndReturn, executor2);
randomSleepAndReturn();
CompletableFuture.allOf(cf1, cf2, cf3)
.thenRun(() -> System.out.println("allOf() commpleted on "
+ Thread.currentThread().getName()));
executor1.shutdown();
executor2.shutdown();
}
public int randomSleepAndReturn() {
try {
final long millis = random.nextInt(1000);
System.out.println(
Thread.currentThread().getName() + " waiting for " + millis);
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 0;
}
}
pool-1-thread-1 waiting for 937
pool-1-thread-2 waiting for 631
main waiting for 776
pool-2-thread-1 waiting for 615
allOf() commpleted on pool-1-thread-1
pool-1-thread-1 waiting for 308
pool-1-thread-2 waiting for 788
main waiting for 389
pool-2-thread-1 waiting for 863
allOf() commpleted on pool-2-thread-1
allOf().thenRun()
):pool-1-thread-1 waiting for 168
pool-1-thread-2 waiting for 292
main waiting for 941
pool-2-thread-1 waiting for 188
allOf() commpleted on main
allOf()
(or anyOf()
)Since there is no guarantee on the executor that will be used, a call to one of those methods should be followed by a *Async(, executor)
call to control which executor will be used.
If you need to return the resulting CompletableFuture
of one of those calls, just add a thenApplyAsync(i -> i, executor)
before returning it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With