Google Guava Concurrency – ListenableFuture
Monitor
class from the com.google.common.util.concurrent package in the Guava Library. In this post I am going to continue my coverage of Guava concurrency utilities and discuss the ListenableFuture
interface. A ListenableFuture
extends the Future
interface from the java.util.concurrent package, by adding a method that accepts a completion listener.ListenableFuture
a ListenableFuture
behaves in exactly the same manner as a java.util.concurrent.Future
but has the method addCallback(Runnable, ExecutorService)
that executes the callback in the given executor
. Here is an example:
ListenableFuture futureTask = executorService.submit(callableTask) futureTask.addListener(new Runnable() { @Override public void run() { ..work after futureTask completed } }, executorService);
If the submitted task has completed when you add the callback, it will run immediately. Using the addCallback
method has a drawback in that the Runnable
does not have access to the result produced by the future
. For access to the result of the Future
you would need to use a FutureCallback
.
FutureCallback
A FutureCallback
accepts the results produced from the Future
and specifies onSuccess
and onFailure
methods. Here is an example:
class FutureCallbackImpl implements FutureCallback<String> { @Override public void onSuccess(String result){ .. work with result } @Override public void onFailure(Throwable t) { ... handle exception } }
A FutureCallback
is attached by using the addCallback
method in the Futures class:
Futures.addCallback(futureTask, futureCallbackImpl);
At this point you may be asking how do you get an instance of ListenableFuture
, when an ExecutorService
only returns Futures
? The answer is to use the ListenableExecutionService
.
ListenableExecutionService
To use a ListenableExecutionService
simply decorate an ExecutorService
instance with a call to MoreExecutors.listeningDecorator(ExecutorService)
for example:
ExecutorsService executorService = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
Conclusion
With the ability to add a callback, whether a Runnable
or the FutureCallback
that handles success and failure conditions, the ListenableFuture
could be a valuable addition to your arsenal. I have created a unit-test demonstrating using the ListenableFuture
available as a gist. In my next post I am going to cover the Futures
class, which contains static methods for working with futures
.
Resources
Reference: Google Guava Concurrency – ListenableFuture from our JCG partner Bill Bejeck at the Random Thoughts On Coding blog.