java ListenableFuture、FutureCallback 和超时

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12380726/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 08:40:11  来源:igfitidea点击:

ListenableFuture, FutureCallback and timeouts

javaguava

提问by Nick Campion

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.

根据我所看到的番石榴示例,我一直在为我的问题寻找优雅的解决方案。具体来说,我喜欢这种工作方式Futures.addCallback(ListenableFuture, FutureCallback),但我希望能够对调用 FutureCallback 之前可以到期的时间长度设置超时。最理想的是,如果违反超时只是导致调用 FutureCallback 的失败条件,那就太好了。

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.

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

采纳答案by Chris Povirk

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

更新:这已作为Futures.withTimeout().



Internally, we have a makeTimeoutFuturemethod that takes a Futureas input and returns a new Futurethat will have the same result unlessthe original hasn't completed by a given deadline. If the deadline expires, the output Futurehas its result set to a TimeoutException. So, you could call makeTimeoutFutureand attach listeners to the output Future.

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

makeTimeoutFutureisn'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?

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

(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 TimeoutExceptionwrapped in an ExecutionException) if the specified duration expires. The delegate future is not cancelled in this case.

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

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