ListenableFuture,FutureCallback和超时 [英] ListenableFuture, FutureCallback and timeouts

查看:198
本文介绍了ListenableFuture,FutureCallback和超时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

Guava有这样的东西吗?是不是不建议尝试将超时与回调相结合?

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

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

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);
    }
}

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

推荐答案

更新:这已添加到Guava中 Futures.withTimeout()

Update: This has been added to Guava as Futures.withTimeout().

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

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 对您的问题不是最自然的解决方案。事实上,我认为该方法的创建主要是为了在no-arg get()调用上设置硬超时,因为将期望的截止日期传播到所有来电者。一个更自然的解决方案是将 get()归结为 get(long,TimeUnit) addCallback(ListenableFuture,FutureCallback) addCallback(ListenableFuture,FutureCallback,long,TimeUnit,SchededuledExecutorService)。这有点笨拙,虽然不如 makeTimeoutFuture 。在做出任何承诺之前,我想更多地考虑这个问题。您是否会提交功能请求

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)

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

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);

这篇关于ListenableFuture,FutureCallback和超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆