Future is just get Interface while Guava ListenableFuture is Future interface with registered Runnable listener(s) run by complete() when set or setException (implemented by guava AbstractFuture).
import com.google.common.util.concurrent.AbstractFuture;
import java.util.concurrent.Future;
public class ListenerFuture<V> extends AbstractFuture<V> {
public ListenerFuture(Future<V> future){
this.future= future;
}
// blocking in future get, then run listener in AbstractFuture set
public void fireListener(){
try {
super.set(future.get());
}catch (Exception e){
throw new RuntimeException("guava set ListenableFuture", e);
}
}
private Future<V> future;
}
ListenerFuture<V> response= new ListenerFuture(service.response());
response.addListener(Runnable, Executor);
// pass the ListenableFuture to whom need it
// do something else until who must have service response call the blocking
response.fileListner()
Guava AbstractFuture has its limitations:
- Listener is lists, but usually only 1 used - overkill. If multiple listeners are needed, fork it inside your listener or think about your design using messaging.
- setException set return value as Exception, so user has to use instanceof to differentiate Exception or not at get()
- In Future pipeline, too many layers addListener() make code hard to read.
I prefer CompletableFuture.supply().thenApply().thenAccept().handle()