2013-07-02 24 views
6

Ho un set di Futures creato inviando Callable s a un Executor. Pseudo codice:Timeout in attesa del completamento di un lotto di futures?

for all tasks 
    futures.add(executor.submit(new callable(task))) 

Ora mi piacerebbe ottenere tutti i futures in attesa al massimo n secondi fino al completamento. So che posso chiamare lo Future#get(timeout) ma se lo chiamo in sequenza per tutti i miei futuri in un ciclo, i timout iniziano a sommarsi. pseudo codice:

for all futures 
    future.get(timeout) 

get blocchi con un timeout finché il risultato è pronto. Pertanto, se il primo viene completato prima del timeout e il secondo viene completato anche prima del timeout e così via, l'intero tempo di esecuzione è number of futures * timeout al massimo anziché timeout.

Quindi, sto cercando un metodo che accetta un elenco di Future s e un timeout, viene eseguito tutto in parallelo e quindi restituisce una raccolta di risultati futuri. Qualche idea?

+0

Questo non è completamente chiaro. Cosa vuoi che succeda alle attività che non sono state completate quando scade il timeout? Vuoi che vengano cancellati o autorizzati a continuare? –

+0

Dovrebbero essere cancellati. Inoltre, in qualche modo ho bisogno di sapere quali sono stati completati e quali no. Immagino che potrei ripetere ancora una volta il futuro e invocare "isDone" su tutti loro. –

risposta

5

È possibile utilizzare ExecutorService.invokeAll:

esegue i compiti assegnati, restituendo una lista di Futures tenendo il loro stato e dei risultati quando tutto completa o il timeout scade, se precedente. Future.isDone() è vero per ogni elemento dell'elenco restituito. Al ritorno, le attività che non sono state completate vengono annullate. Si noti che un'attività completata potrebbe essere terminata normalmente o generando un'eccezione. I risultati di questo metodo non sono definiti se la raccolta specificata viene modificata mentre questa operazione è in corso.


Se si dispone già di Future s che è necessario monitorare e non è possibile utilizzare invokeAll, si può semplicemente misurare il timeout da soli. pseudo codice:

long endTime = System.currentTimeMillis() + timeoutMS; 
for(f : futures) 
    f.get(Math.max(0, endTime - System.currentTimeMillis()), TimeUnit.MILLISECONDS); 

In questo modo si dà ogni futuro al massimo la durata che è rimasto fino a raggiungere il timeout.

+0

'ExecutorService.invokeAll' suona come quello che sto cercando, grazie. Per tutti i futures che non sono stati completati in tempo 'isCancelled == true', giusto (è così che interpreto Javadoc)? Come potrei scoprire se un 'Future' è completato con un'eccezione? "Notare che un'attività completata potrebbe essere terminata normalmente o lanciando un'eccezione" - è difficile ... –

+1

@ MarcelStör Sì, i future non completati vengono annullati ('isCancelled() == true'). Quindi si determina cosa è successo a un "Futuro" quando si chiama ['get()'] (http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html# ottenere% 28% 29) (dopo i ritorni di 'invokeAll'). Se 'get' lancia' CancellationException', sai che è stato cancellato. Se lancia 'ExecutionException', significa che il' Future' è completato da un'eccezione e l'eccezione è accessibile tramite 'ExecutionException.getCause()'. –

Problemi correlati