根据番石榴的例子,我看到我一直在寻找解决问题的优雅方案。具体来说,我喜欢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
。
答案 0 :(得分:23)
更新:这已添加到番石榴Futures.withTimeout()
。
在内部,我们有一个makeTimeoutFuture
方法,该方法将Future
作为输入,并返回一个新的Future
,它将具有相同的结果,除非原始的hasn在给定的截止日期前完成。如果截止日期到期,则输出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)
如果指定的持续时间到期,则返回委托给另一个的未来,但会提前完成(通过TimeoutException
中包含的ExecutionException
)。在这种情况下,代表的未来不会被取消。
scheduledExecutor.schedule(new Runnable() {
@Override public void run() {
TimeoutFuture.this.setException(new TimeoutException("Future timed out"));
}
}, duration.getMillis(), TimeUnit.MILLISECONDS);