35

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.

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.

4

1 に答える 1

25

更新:これはGuavaにとして追加されましたFutures.withTimeout()


内部的には、入力としてを受け取り、元の値が指定された期限までに完了していない限り、同じ結果になる新しい値を返すmakeTimeoutFutureメソッドがあります。期限が切れると、出力の結果はに設定されます。したがって、リスナーを呼び出して出力にアタッチできます。FutureFutureFutureTimeoutExceptionmakeTimeoutFutureFuture

makeTimeoutFutureあなたの問題に対する最も自然な解決策ではありません。実際、このメソッドは主に引数なしの呼び出しにハードタイムアウトを設定するために作成されたと思います。これはget()、すべての呼び出し元に目的の期限を伝播するのが面倒な場合があるためです。より自然な解決策は、それをそのまま推論get()するget(long, TimeUnit)ことaddCallback(ListenableFuture, FutureCallback)ですaddCallback(ListenableFuture, FutureCallback, long, TimeUnit, SchededuledExecutorService)。。よりは少ないですが、それは少し不器用ですmakeTimeoutFuture。何かに取り組む前に、これについてもっと考えたいと思います。機能リクエストを提出しますか?

(これが私たちの内部にあるものです:)

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);
于 2012-09-12T21:51:52.073 に答える