Based on the examples of guava I\'ve seen I\'ve been looking for elegant solutions to my problem. Specifically, I like the way Futures.addCallback(ListenableFuture, FutureCallba
Update: This has been added to Guava as Futures.withTimeout().
Internally, we have a makeTimeoutFuture
method that takes a Future
as input and returns a new Future
that will have the same result unless the original hasn't completed by a given deadline. If the deadline expires, the output Future
has its result set to a TimeoutException
. So, you could call makeTimeoutFuture
and attach listeners to the output Future
.
makeTimeoutFuture
isn't the most natural solution for your problem. In fact, I think that the method was created primarily to set a hard timeout on no-arg get()
calls, since it can be a pain to propagate the desired deadline to all callers. A more natural solution is to reason that get()
is to get(long, TimeUnit)
as addCallback(ListenableFuture, FutureCallback)
is to addCallback(ListenableFuture, FutureCallback, long, TimeUnit, SchededuledExecutorService)
. That's a little clumsy, albeit less so than makeTimeoutFuture
. I'd want to give this more thought before committing to anything. Would you file a feature request?
(Here's what we have internally:)
public static <V> ListenableFuture<V> makeTimeoutFuture(
ListenableFuture<V> delegate,
Duration duration,
ScheduledExecutorService scheduledExecutor)
Returns a future that delegates to another but will finish early (via a TimeoutException
wrapped in an ExecutionException
) if the specified duration expires. The delegate future is not cancelled in this case.
scheduledExecutor.schedule(new Runnable() {
@Override public void run() {
TimeoutFuture.this.setException(new TimeoutException("Future timed out"));
}
}, duration.getMillis(), TimeUnit.MILLISECONDS);