2012-09-12 2 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

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


内部的には、我々は、入力としてFutureを取り、元が与えられた期限までに完了していないない限り、同じ結果を持つことになり、新たなFutureを返すmakeTimeoutFuture方法があります。期限が切れると、出力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) 

は、指定した期間が満了した場合、他に委譲しかし、早期(ExecutionExceptionに包まれたTimeoutException経由)に終了しますという未来を返します。この場合、代表者の未来は取り消されません。

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)のリクエストをオープンしました。 –