I have two ListenableFutures which are completed on other threads. Each future is of a different type, and I wish to use both of their results when they are both complete.
Is there an elegant way to handle this using Guava?
ListenableFuture One lacking feature when using java.util.concurrent.Future is the ability to add listeners to run on completion, which is a common feature provided by most popular asynchronous frameworks. Guava solves this problem by allowing us to attach listeners to its com.google.common.util.concurrent.ListenableFuture.
ListenableFuture One lacking feature when using java.util.concurrent.Future is the ability to add listeners to run on completion, which is a common feature provided by most popular asynchronous frameworks. Guava solves this problem by allowing us to attach listeners to its com.google.common.util.concurrent.ListenableFuture. 2.3. Futures
This is because Guava executes all listeners in a while loop in their respective Executors, but the directExecutor will cause the listener to run in the same thread as the while loop. 5.3. Nesting Futures Is Bad
Guava is among the most nutritious fruits. Common types of guava include pineapple guava, lemon guava, and common guava. For details about the uses and types of guava, follow along with this handy article.
Runnable listener = new Runnable() {
private boolean jobDone = false;
@Override
public synchronized void run() {
if (jobDone || !(future1.isDone() && future2.isDone())) {
return;
}
jobDone = true;
// TODO do your job
}
};
future1.addListener(listener);
future2.addListener(listener);
Not really elegant, but should do the job.
Or, more elegant, but you'll need casts:
ListenableFuture<List<Object>> composedFuture =
Futures.allAsList(future1, future2);
Since Guava v20.0 you can use:
ListenableFuture<CombinedResult> resultFuture =
Futures.whenAllSucceed(future1, future2)
.call(callableThatCombinesAndReturnsCombinedResult, executor);
Look at java docs example here
If you want some sort of type safety you can do the following:
class Composite {
public A a;
public B b;
}
public ListenableFuture<Composite> combine(ListenableFuture<A> futureA,
final ListenableFuture<B> futureB) {
return Futures.transform(futureA, new AsyncFunction<A, Composite>() {
public ListenableFuture<Composite> apply(final A a) throws Exception {
return Futures.transform(futureB, new Function<B, Compisite>() {
public Composite apply(B b) {
return new Composite(a, b);
}
}
}
}
}
ListenableFuture<A> futureA = ...
ListenableFuture<B> futureB = ...
ListenableFuture<Composite> result = combine(futureA, futureB);
In this case Composite
can be a Pair<A, B>
from Apache Commons if you like.
Also, a failure in either future will result in a failure in the resulting combined future.
Another solution would be to take a look at Trickle from the team at Spotify. The GitHub README has an example which shows a solution to a similar problem.
There are undoubtedly other solutions but this is the one that popped into my head.
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