7
votes

What is the difference between Futures.addCallBack() and Futures.transform() in Google Guava Concurrency.

As per the documentation:

Futures.addCallBack():
addCallback(ListenableFuture<V> future, FutureCallback<? super V> callback) Registers separate success and failure callbacks to be run when the Future's computation is complete or, if the computation is already complete, immediately.

Futures.transform():
transform(ListenableFuture<I> input, AsyncFunction<? super I,? extends O> function) Returns a new ListenableFuture whose result is asynchronously derived from the result of the given Future.

As per my understanding addCallback() will register success or failure callback when asynchronous processing is completed. In this case we can handle the out put based on success or failure conditions (example: logging, flow control..etc). and transform() only return the Asynchronous object back. So difference is only Callback?.

  1. whether my understanding is correct?
  2. Which is the best one to use with asynchronous processing?
  3. If I need to call multiple asynchronous methods in a sequence, is there any best practice for that?
  4. What is the difference between using AsyncFunction and Function in transform(ListenableFuture<I> input, Function/AsyncFunction <? super I,? extends O> function)? (AsyncFunction only used for nested Futures.transform()?)

What I tried:
I try to write code like below, whether this is a good practice or not.

public ListenableFuture<MyObject> doSomething() {
    logger.info( "Entered in dosomething() Method." );  

    ListeningExecutorService executor =
            MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(50));

    ListenableFuture<MyObject> myAsyncObject =
            calculator.calculateSomething(input);
    //internally calculator.calculateSomething() have multiple asynchronous
    // calls and I am using Futures.transform(), without callback.

    Futures.addCallback(myAsyncObject, new FutureCallback<MyObject>() {
        public void onSuccess(MyObject result) {
            logger.info( "Calculation Completed successfully." );
            //TODO: check for success and log it.
        }

        public void onFailure(Throwable thrown) {
            logErrorDetails(thrown);
        }
    }, executor);

    executor.shutdown();

    return myAsyncObject;
}
1
The difference is in how you use it. Transformations can be piped together whereas normal callbacks are terminating.ooxi
Note that you'll have problems running your callback (in the future) on an executor that you shut down now (sequentially with the addition of the callback). You also usually don't want to create a different executor for each invocation of the method.Frank Pavageau

1 Answers

1
votes

Well you didn't write the full method signature in your question

  • addCallback returns nothing
  • transform returns a future that holds result of the function (if the input succeeded) or the original input's failure (if not). This allows to chain transformations, with a fluent syntax.

I've not used AsyncFunction, but I understand they add one level of asynchronicity, ie the result of the Future is another Future.