Google Guava Concurrency - ListenableFuture
by Bill Bejeck
In my last post I covered using the 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
Subscribe via RSS