2012-02-17 13 views
12

Qualcuno può indicarmi una documentazione che chiarisca che un 'Future.get` con un timeout di 0 non aspetterà?Comportamento di future.get con 0 timeout

I documenti API per java.util.concurrent.Future non rendono esplicito il comportamento di future.get(0, unit). Stando da solo, l'affermazione "Aspetta se necessario per al massimo il tempo stabilito ..." implica che questa invocazione non aspetterà affatto, ma dato il comportamento di vecchia data di Object.wait(0) (attesa infinita), sono nervoso per dipendere su un comportamento "nessuna attesa" di future.get(0, unit)

Scansione la fonte di alcune classi JDK fornito (vale a dire. FutureTask) vedo che questa particolare implementazione di Future non aspetta quando il timeout è 0.

I' mi piacerebbe poter dire

long timeout = Math.max(until - now, 0); 
    return future.get(timeout, TimeUnit.MILLISECONDS); 

ma sono nervoso per un futuro applicazione di tale come un attesa infinita, così invece, ho codificato esplicitamente il modo in cui mi aspetterei che funzioni:

long timeout = Math.max(until - now, 0); 
    if(timeout > 0 || future.isDone()){ 
     return future.get(timeout, TimeUnit.MILLISECONDS); 
    } else { 
     throw TimeoutException(); 
    } 
+0

@skaffman Grazie per la correzione dei tag. – mwhidden

risposta

7

Waits se necessario per al massimo il tempo determinato & hellip;

Aspettando al massimo pari a zero unità di tempo non aspetta affatto. Questo non è un suggerimento implicito, è una garanzia esplicita.

+3

concesso. Ho pensato che questa differenza di semantica da 'Object.wait (long)' avrebbe giustificato una distinzione esplicita fatta nei documenti. Anche 'Object.wait' all'inizio sembra non garantire alcuna attesa" timeout "- il tempo massimo di attesa in millisecondi" ma poi i backpard e dice "Se timeout" è zero, tuttavia, il tempo reale non viene preso in considerazione e il thread attende semplicemente fino alla notifica ". – mwhidden

5

posso puntare ad un certo codice se questo aiuta. Guardando in java.util.concurrent.FutureTask e poi a AbstractQueuedSynchronizer vedo il seguente ciclo che ho ridotto al mostrare i bit relavent:

private boolean doAcquireSharedNanos(int arg, long nanosTimeout) { 
    long lastTime = System.nanoTime(); 
    for (;;) { 
     ... 
     if (nanosTimeout <= 0) { 
      cancelAcquire(node); 
      return false; 
     } 
     long now = System.nanoTime(); 
     nanosTimeout -= now - lastTime; 
    } 

Questo significa che se nanosTimeout è 0 (che sarà se si passa a 0 a get) allora proverà ad acquisire il futuro una volta e poi a timeout e restituirà false.

Se ti fa sentire meglio, puoi impostare il tuo timeout in 1 nanosecondo.

+0

Grazie! Questo è esattamente il codice che ho recensito durante le mie ricerche. – mwhidden