35

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, FutureCallback) works, but I'd like to be able to set a timeout on the length of time that can expire before the FutureCallback is invoked. Optimally It would be nice if breaching the timeout just caused an the failure condition of FutureCallback to be called.

Does Guava have something like this already? Is it just not recommended to try to couple timeouts with the callbacks?

EDIT: Including example of the code that led me to this point. Obviously, I stripped out the meaningful bits to get a minimum example.

@Test
public void testFuture()
{
    Callable<Boolean> callable = new Callable<Boolean>()
    {

        @Override
        public Boolean call() throws Exception
        {
            while(true);
        }
    };

    ListenableFuture<Boolean> callableFuture = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()).submit(callable);

    Futures.addCallback(callableFuture, new FutureCallback<Boolean>()
    {

        @Override
        public void onFailure(Throwable arg0)
        {
            System.out.println("onFailure:"+arg0); 
        }

        @Override
        public void onSuccess(Boolean arg0)
        {
            System.out.println("onSuccess:"+arg0);
        }
    }); 

    try
    {
        callableFuture.get(1000, TimeUnit.MILLISECONDS);
    }catch(Throwable t)
    {
        System.out.println("catch:"+t);
    }
}

This code will only print catch:java.util.concurrent.TimeoutException.

4

1 回答 1

25

更新:这已被添加到 Guava 作为Futures.withTimeout().


在内部,我们有一个makeTimeoutFuture方法,它将 aFuture作为输入并返回一个Future具有相同结果的新方法,除非原始方法在给定的截止日期之前没有完成。如果截止日期到期,则输出Future的结果设置为 a TimeoutException。因此,您可以调用makeTimeoutFuture并将侦听器附加到 output Future

makeTimeoutFuture不是解决您的问题的最自然的解决方案。事实上,我认为创建该方法的主要目的是为无参数get()调用设置硬超时,因为将所需的截止日期传播给所有调用者可能会很痛苦。一个更自然的解决方案是按get()原样get(long, TimeUnit)推理。这有点笨拙,尽管不如. 在做任何事情之前,我想多考虑一下。您会提交功能请求吗?addCallback(ListenableFuture, FutureCallback)addCallback(ListenableFuture, FutureCallback, long, TimeUnit, SchededuledExecutorService)makeTimeoutFuture

(这是我们内部拥有的:)

public static <V> ListenableFuture<V> makeTimeoutFuture(
    ListenableFuture<V> delegate,
    Duration duration,
    ScheduledExecutorService scheduledExecutor)

返回一个委托给另一个的未来,但如果指定的持续时间到期,它将提前完成(通过TimeoutException包装在 an 中)。ExecutionException在这种情况下,委托未来不会被取消。

scheduledExecutor.schedule(new Runnable() {
  @Override public void run() {
    TimeoutFuture.this.setException(new TimeoutException("Future timed out"));
  }
}, duration.getMillis(), TimeUnit.MILLISECONDS);
于 2012-09-12T21:51:52.073 回答