2012-09-12 35 views
32

基于番石榴的例子,我见过我一直在寻找优雅的解决方案来解决我的问题。具体来说,我喜欢Futures.addCallback(ListenableFuture, FutureCallback)的工作方式,但我希望能够设置在FutureCallback被调用之前可以过期的时间长度超时。理想情况如果违反超时只会导致FutureCallback的失败情况被调用,那将是非常好的。ListenableFuture,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

回答

21

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


在内部,我们有一个makeTimeoutFuture方法,它接受Future作为输入,并返回一个新的Future,将有相同的结果除非原来一直未在规定限期完成。如果截止日期到期,输出Future将其结果设置为TimeoutException。因此,您可以拨打makeTimeoutFuture并将听众附加到输出Future

makeTimeoutFuture不是您的问题最自然的解决方案。实际上,我认为该方法主要是为了在no-arg 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); 
+0

非常感谢。我打开了请求[此处](http://code.google.com/p/guava-libraries/issues/detail?id=1146&thanks=1146&ts=1347504235)。 –