2012-09-12 8 views
32

Basado en los ejemplos de guayaba que he visto, he estado buscando soluciones elegantes para mi problema. Específicamente, me gusta la forma en que funciona Futures.addCallback(ListenableFuture, FutureCallback), pero me gustaría poder establecer un tiempo de espera sobre el período de tiempo que puede caducar antes de invocar FutureCallback. Óptimo Sería bueno si incumplir el tiempo de espera solo causara que se llame a la condición de falla de FutureCallback.ListenableFuture, FutureCallback y timeouts

¿La guayaba ya tiene algo como esto? ¿No es recomendable intentar emparejar tiempos de espera con las devoluciones de llamada?

EDITAR: Incluye ejemplo del código que me llevó a este punto. Obviamente, eliminé las partes significativas para obtener un ejemplo mínimo.

@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); 
    } 
} 

Este código solo se imprimirá catch:java.util.concurrent.TimeoutException.

Respuesta

21

Actualización: Esto ha sido agregado a Guava como Futures.withTimeout().


Internamente, tenemos un método que toma un makeTimeoutFutureFuture como entrada y devuelve una nueva Future que tendrá el mismo resultado menos que el original no se ha completado en un plazo determinado. Si la fecha límite expira, la salida Future tiene su resultado establecido en TimeoutException. Por lo tanto, puede llamar al makeTimeoutFuture y adjuntar detectores a la salida Future.

makeTimeoutFuture no es la solución más natural para su problema. De hecho, creo que el método fue creado principalmente para establecer un tiempo de espera extenuante en las llamadas no-arg get(), ya que puede ser difícil propagar la fecha límite deseada para todas las personas que llaman. Una solución más natural es razonar que get() es a get(long, TimeUnit) como addCallback(ListenableFuture, FutureCallback) es a addCallback(ListenableFuture, FutureCallback, long, TimeUnit, SchededuledExecutorService). Eso es un poco torpe, aunque menos que makeTimeoutFuture. Me gustaría pensar más en esto antes de comprometerme con algo. ¿Podrías file a feature request?

(Esto es lo que tenemos internamente :)

public static <V> ListenableFuture<V> makeTimeoutFuture(
    ListenableFuture<V> delegate, 
    Duration duration, 
    ScheduledExecutorService scheduledExecutor) 

Devuelve un futuro que delegue en otro, pero terminarán temprano (a través de un TimeoutException envuelto en una ExecutionException) si la duración especificada expira. El futuro delegado no se cancela en este caso.

scheduledExecutor.schedule(new Runnable() { 
    @Override public void run() { 
    TimeoutFuture.this.setException(new TimeoutException("Future timed out")); 
    } 
}, duration.getMillis(), TimeUnit.MILLISECONDS); 
+0

Gracias por la entrada. Abrí la solicitud [aquí] (http://code.google.com/p/guava-libraries/issues/detail?id=1146&thanks=1146&ts=1347504235). –

Cuestiones relacionadas