As per Oracle documentation :
invokeAll() : Executes the given tasks, returning a list of Futures holding their status and results when all complete. Future.isDone() is true for each element of the returned list. Note that a completed task could have terminated either normally or by throwing an exception. The results of this method are undefined if the given collection is modified while this operation is in progress.
CompletableFuture also implements Future with the following policies:
Since (unlike FutureTask) this class has no direct control over the computation that causes it to be completed, cancellation is treated as just another form of exceptional completion. Method cancel has the same effect as completeExceptionally(new CancellationException()). Method isCompletedExceptionally() can be used to determine if a CompletableFuture completed in any exceptional fashion.
In case of exceptional completion with a CompletionException, methods get() and get(long, TimeUnit) throw an ExecutionException with the same cause as held in the corresponding CompletionException. To simplify usage in most contexts, this class also defines methods join() and getNow(T) that instead throw the CompletionException directly in these cases.
What are the differences between
invokeAll() with Future
CompletableFuture
Since JDK 1.7 does not support CompletableFuture, can the same result will be achieved with invokeAll() with Future?
Of course you can, if you write a bit of code:
Copy/implement (the needed/related parts from) the CompletableFuture. For an example check this implementation on grepcode.
Extend an ExecutorService (that you already use), and extend the protected method newTaskFor() responsible for instantiating Futures from a Runnable or a Callable, creating a new CompletableFuture() in it.
Related
I created a java thread pool using
dbChangeService = Executors.newSingleThreadExecutor();
I have implemented a runnable interface and added it to
Future future = dbChangeService.submit(dbChgProcessor);
when I do future.isDone() it returns false which is understandable because I am checking immediately after submitting.
What is the correct way of using Future.isDone() method so that it can produce meaningful results.
PS: I don't want to use Future.get() which is a blocking call.
Instead of simply doing future.isDone(), you should poll for it to be true. E.g.
while(!future.isDone())
{
log.info("future not done yet, waiting before retrying...");
Thread.sleep(300);
}
Object result = future.get();
This still is still kind of blocking, so you probably wanna do it on another thread that will notify your main tread using a lock object. Or even better why not use CompletableFuture? See resources here & here.
So first of all let me clarify that:
Future.isDone() tells us if the executor has finished processing the task.
If the task is complete, it will return true otherwise, it returns false.
I would suggest you to use CompletableFuture, something like:
CompletableFuture.supplyAsync(() -> {
...
});
This will return a CompletableFuture as well.
As I said in the comments, a CompletableFuture provides a broad set of methods for creating multiple Futures, chaining, and combining. It also has comprehensive exception handling support
Check a full guide with CompletableFuture examples here
The API says:
“Method invokeAll (available in multiple versions) performs the most common form of parallel invocation: forking a set of tasks and joining them all.”
So my assumption is if I use invokeAll(), I no longer need to use fork() or join() methods. I also know that in general, join() is called only if the task returns a value: a subclass of: RecursiveTask and not used if the task not returning a value: subclass of: RecursiveAction.
I came across this tutorial which has called ForkJoinTask.join() after its called: invokeAll():
https://www.baeldung.com/java-fork-join
#Override
protected Integer compute() {
if (arr.length > THRESHOLD) {
return ForkJoinTask.invokeAll(createSubtasks())
.stream()
.mapToInt(ForkJoinTask::join) // join() is called
.sum();
} else {
return processing(arr);
}
}
Also this post, which has used join() after calling invokeAll():
Why should we call join after invokeAll method?
invokeAll(subTask1, subTask2);
return subTask1.join() + subTask2.join();
At the same time, I looked at many other examples for invokeAll() and there is NO join() after that call.
1) Is there any rule that when we should or should not use join() after invokeAll()?
2) invokeAll() comes in three different signatures, is this depending on the signature of the method to decide whether to use join() or not?
3) On the same note, I also read this in the API:
"Method invoke() is semantically equivalent to fork(); join() but always attempts to begin execution in the current thread."
Is it saying that invoke() is equal to fork() plus join()?
Call join() when you need the results of the computation. There is no rule regarding when. If you have other work to do you can do that, if you have no other work to do and you need the results from the computation, call join()
The signatures reflect the different ways of supplying the tasks. With one they come from a collection, with another they come from varargs or an array, with the third you supply two as arguments. Otherwise there is no difference between them. Use the one that is most convenient.
fork(); join() is asynchronous, the work by fork is in another thread and the current thread waits for the work to complete when join is called. invoke() does the same work but in the current thread.
I have a utility method (used for unit testing, it so happens) that executes a Runnable in another thread. It starts the thread running, but does not wait for the Thread to finish, instead relying on a Future. A caller of the method is expected to get() that Future. But is that enough to ensure safe publication of the computation done by the Runnable?
Here is the method:
private static Future<Void> runInOtherThread(final CountDownLatch ready, final Runnable operation) {
final CompletableFuture<Void> future = new CompletableFuture<Void>();
final Thread thread = new Thread(() -> {
try {
ready.await();
operation.run();
} catch (Throwable e) {
future.completeExceptionally(e);
return;
}
future.complete(null);
});
thread.start();
return future;
}
After calling Future.get() on the returned Future, can the caller of the method safely assume that the Runnable has finished execution, and its results have been safely published?
No you don't need to join(). Calling get() on the future is sufficient.
The CompletableFuture interface is a subtype of Future. And the javadoc for Future states this:
Memory consistency effects: Actions taken by the asynchronous computation happen-before actions following the corresponding Future.get() in another thread.
That happen-before relationship is sufficient to ensure safe publication of the value returned by get().
Furthermore, the get() call will not complete until the CompletableFuture has been completed, exceptionally-completed or cancelled.
If we look at Safe Publication by Shipilev one of the trivial ways to get safe publication is to work:
Exchange the reference via a volatile field (JLS 17.4.5), or as the consequence of this rule, via the AtomicX classes
Since CompletableFuture uses a volatile field to write and read the value no additional memory barriers are necessary for safe publication. This is explained in CompletableFuture class overview comment:
* A CompletableFuture may have dependent completion actions,
* collected in a linked stack. It atomically completes by CASing
* a result field, and then pops off and runs those actions. This
* applies across normal vs exceptional outcomes, sync vs async
* actions, binary triggers, and various forms of completions.
*
* Non-nullness of volatile field "result" indicates done. It may
* be set directly if known to be thread-confined, else via CAS.
* An AltResult is used to box null as a result, as well as to
* hold exceptions.
It also handles the safe initialization of the published objects, as per the same overview comment later:
* Completion fields need not be declared as final or volatile
* because they are only visible to other threads upon safe
* publication.
From this answer I learned that the only difference between Callable and Runnable is that former can return a result of the execution and throw an exception.
I don't understand why Executor doesn't define a method which takes a Callable:
void execute(Callable command);
From my point of view, it'd be logical to create methods for both Runnable and Callable. In ExecutorService, which is a subinterface of Executor, there are similar submit() methods for both Runnable and Callable.
Please, explain this design decision, because I can't find any explanation on the Internet.
I don't understand why Executor doesn't define a method which takes a Callable.
An Executor has a single responsibility - executing a submitted task. On this abstraction level, APIs that use only Runnables don't demand the additional features proposed by the ExecutorService.
It'd be logical to create methods for both Runnable and Callable.
Yes, therefore the ExecutorService interface was designed by extending the Executor. The ExecutorService offers a significant difference - providing results of task execution. That's why the Callable, TimeUnit, and lifecycle methods were added.
I suppose the Executor design was meant to be as simple as possible, i.e. with one method. Since execute() doesn't provide any means of getting the result, it makes sense that it doesn't accept Callables, and takes only Runnables.
On the other hand, the various submit() functions return Futures, which can be used to both obtain a result (e.g. from a Callable), or to simply wait for the execution to finish. So, it makes sense to accept both Runnable and Callable.
Executors run tasks. They are needed if you want to manage how and when tasks should be run. Executors don't collect task results and thus support only Runnable.
Assume they support Callable. Then how should one fetch the result? T execute(Callable<T> command) is not an option as it will block current thread execution. So it should be paired with some T getResult() or return Future<T>. And for that you have ExecutorService with method <T> Future<T> submit(Callable<T> task).
Below is the piece of code that submits a job.. Let's say I have 3 threads running. how does the get method wait and obtain the appropriate thread results.
Future<?> result = threadPool.submitTasks(new Callable<T>() {
public T call() throws Exception {
// do something
}
});
anyType = (T) result.get();
Or Lets say I have Task A resulted 1 and Task B resulted 2.. When it comes to get method, what is the guarantee that it returns the correct values?
Your submitted task (in this case the Callable) is wrapped into the instance of the returned Future. In essence, the Future is directly related to the task it was created for, and not any other task.
Internally, when calling get, the future will attempt to acquire a lock that it shares in common with its wrapped task. Once acquired, it then queries the status of the task in order to determine what to do next:
Throw an exception if the Future was cancelled, or if the underlying task generated an exception
Otherwise, return the result that was generated by the task.
This is broadly how it works, there are several implementations of Future and they all have different internal logic.
You're assuming there is a guarantee they will receive the correct output. This is a question of implementing Thread safe code.
Often, to make an implementation thread safe, you will lock it from use with some sort of flag. This will indicate to other threads that they can not use it.