What is the purpose of java.util.concurrent.CompletableFuture#allOf? - java

If I have Collection<CompletableFuture<MyResult>>, I expect to convert this into CompletableFuture<Collection<MyResult>>. So after conversion I have only one future and can easyly write bussines logic on MyResult collection using methods from CompletableFuture like thenApply, thenAccept etc. But CompletableFuture#allOf have result type Void so after invoking it I get "no results". E.g. I can not retrieve (as I understand) any results from returned future that correspods to Collection<CompletableFuture<MyResult>>.
I have a doubt that CompletableFuture#allOf just return the Future wich is completed after all in collection. So I can invoke CompletableFuture#allOf(...).isDone and then manually (!) in cycle tranform Collection<CompletableFuture> to CompletableFuture<Collection>, Is my assumption right?

Yes, the allOf method does not supply data, but does signal that all futures have been completed. This eliminates the need of using the more cumbersome countdown latch approach. The expectation is that you would then convert the completed futures back into a usable Collection to apply your business logic. See this question for implementation details. A great discussion of this topic is available at this blog post.

if you need CompletableFuture<Collection<MyResult>> as result you can get it by using allAsList method in https://github.com/spotify/completable-futures (spotify-completlablefutures library). CompletableFutures.allAsList(List<CompletableFuture<MyResult>>) will give you CompletableFuture<List<MyResult>>.

Related

How to implement CompletableFuture with a priority execution?

I have an issue where I am not sure if the completable future api is able to solve my problem, but would like to open it to the stack overflow community.
I have a case, where I want to call 2 methods. One of these methods (method A) will return some data from DynamoDB. Another method (method B) will return some data from a SQL database. I would like to do these methods in parallel. However, the twist is the customer can ask for data in a certain priority.
For example, a user could pass in `["A" , "B"]. In this case, I would like both tasks to start being done in parallel, but if A finishes and returns useful data to stop execution on task B. If A returns null/not found, then return the result of B.
When reading about completable future's I have not found any methods that seem to be able to do this. The methods anyOf(CompletableFuture<?>... cfs) or allOf(CompletableFuture<?>... cfs) seem to apply to these situations. It seems like there is no way to give a preference to a specific CompletableFuture.
I would love to know how to solve this problem in Java!

Using ForkJoinPool on a set of documents

I have never used a ForkJoinPool and I came accross this code snippet.
I have a Set<Document> docs. Document has a write method. If I do the following, do I need to have a get or join to ensure that all the docs in the set have correctly finished their write method?
ForkJoinPool pool = new ForkJoinPool(concurrencyLevel);
pool.submit(() -> docs.parallelStream().forEach(
doc -> {
doc.write();
})
);
What happens if one of the docs is unable to complete it's write? Say it throws an exception. Does the code given wait for all the docs to complete their write operation?
ForkJoinPool.submit(Runnable) returns a ForkJoinTask representing the pending completion of the task. If you want to wait for all documents to be processed, you need some form of synchronization with that task, like calling its get() method (from the Future interface).
Concerning the exception handling, as usual any exception during the stream processing will stop it. However you have to refer to the documentation of Stream.forEach(Consumer):
The behavior of this operation is explicitly nondeterministic. For parallel stream pipelines, this operation does not guarantee to respect the encounter order of the stream, as doing so would sacrifice the benefit of parallelism. For any given element, the action may be performed at whatever time and in whatever thread the library chooses. […]
This means that you have no guarantee of which document will be written if an exception occurs. The processing will stop but you cannot control which document will still be processed.
If you want to make sure that the remaining documents are processed, I would suggest 2 solutions:
surround the document.write() with a try/catch to make sure no exception propagates, but this makes it difficult to check which document succeeded or if there was any failure at all; or
use another solution to manage your parallel processing, like the CompletableFuture API. As noted in the comments, your current solution is a hack that works thanks to implementation details, so it would be preferable to do something cleaner.
Using CompletableFuture, you could do it as follows:
List<CompletableFuture<Void>> futures = docs.stream()
.map(doc -> CompletableFuture.runAsync(doc::write, pool))
.collect(Collectors.toList());
This will make sure that all documents are processed, and inspect each future in the returned list for success or failure.

Using Future<V>

In this documentation, it shows an example code for Future<V>, in some GAE datastore ORM's I can see usages for this pattern, what is the implication of using Future on doing datastore put, get or delete methods? What is the common motivation on doing this?
The reason Future is used is because the database operations are done asynchronously, so you can carry on doing whatever and come back to check the result of the database operation.
The implications of an asynchronous store is that you could read a value that is stale, ie a put has been sent but the Future operation is not complete, or worse, the value has already been deleted, but this is something the ORM has hopefully solved for you.
You can use Future.get to block the current thread and wait for the operation to complete and check the result.

Guava ListenableFuture allAsList returns all content seen so far from get

I was wondering if there is any util for ListenableFuture that works like allAsList but if you call get(50, TimeUnit.Milliseconds) returns all that have completed.
No, but there might be in the future as I think the answer resides there as discussed in this related question too:
ListenableFuture, FutureCallback and timeouts
Basically instead of having a special kind of Futures#allAsList(), you could add a callback with timeout on all of your futures and use Futures#successfulAsList() over them. Thus, every future that times out, would fail with a TimeoutException and Futures#successfulAsList() would return only the successful ones, i.e. not those that failed with any kind of exception (including TimeoutException).
Unfortunately, this is not yet implemented in guava (see the first link to guava's tracker issue) but has been accepted at least as a valid request.

Name for pattern in which actions happen upon completion of a future event / Java class

I have a class currently called Promise that works as follows:
It holds a future value
It can always accept a subsequent action to take that uses the future value as the parameter
When the value is completed the function queue launches
Any functions added after the future is complete happen synchronously
So this seems to be a design pattern from functional programming that we're jamming into Java. The important thing is that we can daisy-chain on delayed events, which I understand is a feature more built into C# 3.0 language but you have to hack together with Java classes. Unfortunately, one, I don't know a better name for this than "promise" or "future," which seem misleading since the focus is more on the "DelayedCallStack" then the value at hand, and two, I don't know of any way to do this beyond writing our own fairly complicated Promise class. Ideally I'd like to lift this from the functional Java library but the concept eludes me thus far.
Note Java doesn't even give language/library support for an asynchronous callback that takes a parameter, which is one reason I'm so pessimistic about being able to find this.
So, what is this pattern, can it be done in libraries?
Take a look a ListenableFuture in Guava:
http://code.google.com/p/guava-libraries/wiki/ListenableFutureExplained
ListenableFuture allows you to add callbacks to be executed when the Future computation is completed. You can control what thread pool the callbacks get executed under, so they can be executed synchronously or asynchronously.
I can only say that we implemented pretty much exactly the same thing in Flex (ActionScript) and we also called it a Promise. In Clojure a promise is something quite a bit more lightweight: the get operation on it blocks until another thread delivers the promise. It's basically a one-element queue except that it retains its value forever, so subsequent gets always succeed.
What you have is a kind of a promise coupled with observers of its value. I'm not aware of any special term covering exactly that case.
EDIT
Now I notice that your "promise/future" might own the code that produces its future value (at least it's not entirely obvious whether it does). The ActionScript implementation I mentioned didn't do that -- it behaved like Clojure's, the value being supplied from the outside. I think this is the key distinction between a future and a promise.

Categories

Resources