2015-11-21 12 views
10

Ho ottenuto ConcurrentLinkedDeque che sto utilizzando per gli elementi push/pop sincroni, e ho alcune attività asincrone che prendono un elemento dallo stack e se questo l'elemento ha vicini Lo sta spingendo a impilare.Come verificare se tutte le attività in esecuzione su ExecutorService sono state completate

codice Esempio:

private ConcurrentLinkedDeque<Item> stack = new ConcurrentLinkedDeque<>(); 
private ExecutorService exec = Executors.newFixedThreadPool(5); 

    while ((item = stack.pollFirst()) != null) { 
       if (item == null) { 
       } else { 
        Runnable worker = new Solider(this, item); 
        exec.execute(worker); 
       } 
      } 

    class Solider{ 
     public void run(){ 
      if(item.hasNeighbors){ 
       for(Item item:item.neighbors){ 
        stack.push(item) 
       } 
      } 
     } 
    } 

vorrei avere ulteriore dichiarazione in ciclo while che risponde alla domanda - "qualsiasi operazione in Esecutore sta funzionando?"

risposta

24

Non esiste un modo pulito per verificare se tutti i Runnable sono eseguiti se si utilizza ExecutorService.execute(Runnable). A meno che non si costruisca un meccanismo per farlo nel Runnable stesso (che è sciatto secondo me).

Invece:
Usa ExecutorService.submit(Runnable). Questo metodo restituirà un Future<?> che è un handle per il risultato di un eseguibile. L'utilizzo di Futures fornisce un modo pulito per verificare i risultati.

Tutto quello che dovete fare è mantenere un elenco di Futures che si presenta, e poi si può iterare l'intero elenco dei Futures e sia:
    a) Attendere per tutti i futures per essere fatto in un blocco way o
    B) controlla se tutti i futures sono fatti in modo non bloccante.

Ecco un esempio di codice:

List<Future<?>> futures = new ArrayList<Future<?>>(); 
ExecutorService exec = Executors.newFixedThreadPool(5); 

// Instead of using exec.execute() use exec.submit() 
// because it returns a monitorable future 
while((item = stack.pollFirst()) != null){ 
    Runnable worker = new Solider(this, item); 
    Future<?> f = exec.submit(worker); 
    futures.add(f); 
} 

// A) Await all runnables to be done (blocking) 
for(Future<?> future : futures) 
    future.get(); // get will block until the future is done 

// B) Check if all runnables are done (non-blocking) 
boolean allDone = true; 
for(Future<?> future : futures){ 
    allDone &= future.isDone(); // check if future is done 
} 
+0

ho pensato che ci sia già il metodo in java utilizzato per questo: < ogni caso! Ho usato la tua soluzione funziona, grazie! :) – user4129715

+0

Quale sarebbe lo scopo di allDone qui, non posso il futuro.isDi ritorno vero o falso da solo? BTW - ottima risposta! – User3

+1

@ User3 lo scopo di 'allDone' è quello di ottenere un singolo valore booleano che indica se _all_ dei futuri è fatto o meno (usando l'operatore' & = '). 'future.isDone()' può essere usato solo per verificare se un Futuro individuale è completo o meno –

Problemi correlati