2012-09-12 54 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)。 –