ListenableFuture,FutureCallback和超时

Nic*_*ion 33 java guava

根据番石榴的例子,我看到我一直在寻找解决问题的优雅方案.具体来说,我喜欢这种方式Futures.addCallback(ListenableFuture, FutureCallback) ,但是我希望能够在调用FutureCallback之前的时间长度上设置超时.最佳如果违反超时只会导致调用FutureCallback的失败条件会很好.

番石榴有没有这样的东西?是不是不建议尝试将超时与回调相结合?

编辑:包括引导我到这一点的代码示例.显然,我删除了有意义的位以获得最小的例子.

@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);
    }
}
Run Code Online (Sandbox Code Playgroud)

此代码仅打印catch:java.util.concurrent.TimeoutException.

Chr*_*irk 23

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


在内部,我们有一个makeTimeoutFuture方法,它接受一个Future输入并返回一个Future具有相同结果的新方法,除非原始文件没有在给定的截止日期之前完成.如果截止日期到期,则输出Future的结果将设置为a TimeoutException.因此,您可以调用makeTimeoutFuture并将侦听器附加到输出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)
Run Code Online (Sandbox Code Playgroud)

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

scheduledExecutor.schedule(new Runnable() {
  @Override public void run() {
    TimeoutFuture.this.setException(new TimeoutException("Future timed out"));
  }
}, duration.getMillis(), TimeUnit.MILLISECONDS);
Run Code Online (Sandbox Code Playgroud)