Ответ 1
И ListenableFuture, и CompletableFuture имеют преимущество перед родительским классом Future, позволяя вызывающей стороне так или иначе "зарегистрировать" обратный вызов, который будет вызван после завершения асинхронного действия.
С Future вы можете сделать это:
ExecutorService executor = ...;
Future f = executor.submit(...);
f.get();
f.get()
блокируется, пока не будет выполнено асинхронное действие.
С ListenableFuture вы можете зарегистрировать обратный вызов, как это:
ListenableFuture listenable = service.submit(...);
Futures.addCallback(listenable, new FutureCallback<Object>() {
@Override
public void onSuccess(Object o) {
//handle on success
}
@Override
public void onFailure(Throwable throwable) {
//handle on failure
}
})
С CompletableFuture вы также можете зарегистрировать обратный вызов, когда задача завершена, но она отличается от ListenableFuture тем, что она может быть завершена из любого потока, который хочет ее выполнить.
CompletableFuture completableFuture = new CompletableFuture();
completableFuture.whenComplete(new BiConsumer() {
@Override
public void accept(Object o, Object o2) {
//handle complete
}
}); // complete the task
completableFuture.complete(new Object())
Когда поток вызывает завершение для задачи, значение, полученное от вызова get(), устанавливается со значением параметра, если задача еще не завершена.