【问题标题】:ListenableFuture, FutureCallback and timeoutsListenableFuture、FutureCallback 和超时
【发布时间】:2012-09-12 03:15:29
【问题描述】:

根据我看到的番石榴示例,我一直在寻找优雅的解决方案来解决我的问题。具体来说,我喜欢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);
    }
}

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

【问题讨论】:

    标签: java guava


    【解决方案1】:

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


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

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

    (这是我们内部的:)

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

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

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

    【讨论】:

    • 感谢您的建议。我打开了请求here
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-01
    • 2015-03-05
    • 1970-01-01
    • 2016-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多