Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use the results of two Guava ListenableFutures of different types

Tags:

java

future

guava

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?

like image 999
sdgfsdh Avatar asked Dec 07 '12 12:12

sdgfsdh


People also ask

What is listenablefuture in 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.

What is listenablefuture in Java?

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

Why does guava run in the same thread as the while loop?

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

What are the different types of guava?

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.


3 Answers

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);
like image 117
JB Nizet Avatar answered Oct 11 '22 12:10

JB Nizet


Since Guava v20.0 you can use:

ListenableFuture<CombinedResult> resultFuture =
   Futures.whenAllSucceed(future1, future2)
       .call(callableThatCombinesAndReturnsCombinedResult, executor);

Look at java docs example here

like image 40
Chobicus Avatar answered Oct 11 '22 13:10

Chobicus


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.

like image 9
fido Avatar answered Oct 11 '22 13:10

fido