2012-10-15 11 views
9

Avere il seguente codice a portata di mano:ExecutorService con invokeAll() e futuro in java

ExecutorService executor = Executors.newFixedThreadPool(10); 
    Collection collection = new ArrayList(); 
    for (int n=1; n<100; n++) 
     collection.add(new MyThread(n)); 

    try { 
     List<Future<Boolean>> futures = executor.invokeAll(collection); 

     for(Future<Boolean> future : futures){ 
      future.get(); 
      if (future.isDone()) { 
       System.out.println("true"); 
      } 
      else 
       System.out.println("false"); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

Se quanto sopra è corretto?
E se tutti gli future.isDone() sono veri, allora tutti i thread sono stati eseguiti?
Come posso fare una bandiera, per essere sicuro che siano tutti fatti?

risposta

7

Per controllare se tutti sono vere, si può fare qualcosa di simile:

boolean works=true; 
    for(Future<Boolean> future : futures){ 
     future.get(); 
     if (future.isDone()) { 
      System.out.println("true"); 
     } 
     else{ 
      System.out.println("false");works=false; 
     } 
    } 
if(works)System.out.println("yea it works") 
0

Se il metodo future.get ritorna, il calcolo fatto dal futuro è terminato, quindi chiamare isDone è ridondante. E sì, dopo che tutti i futures hanno terminato tutti i thread nel ThreadPool dovrebbero essere disponibili.

+0

modo che io possa eliminare questa parte? if (future.isDone()) { System.out.println ("true"); } else { System.out.println ("false"); } – fen1ksss

+0

Penso di sì. Il [javadoc] (http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html#get()) per 'Future' afferma che' get' "Aspetta se necessario per il calcolo da completare e quindi recupera il risultato. ". Quindi in realtà è necessario anche racchiudere 'isDone' nel proprio gestore di eccezioni. – vainolo

2

Normalmente si aggiungono attività eseguibili a un pool di thread. Aggiungere thread a un pool di thread non farà ciò che pensi.

Quando future.get() restituisce per ogni attività, tutte le attività sono state completate. I thread che hanno eseguito le attività continueranno a essere in esecuzione.

Se si desidera interrompere tutto il filo una volta che le operazioni hanno completato è possibile utilizzare executor.shutdown(); e executor.awaitTermination


Il modo in cui vorrei scrivere è

ExecutorService executor = Executors.newFixedThreadPool(10); 
List<Future<Boolean>> futures = new ArrayList<>(); 
for (int n = 0; n < 100; n++) 
    futures .add(executor.submit(new MyTask(n)); 

for(Future<Boolean> future : futures) { 
    boolean result = future.get(); 
    // do something with the result. 
} 

Se il risultato non è necessaria a voi fare il tipo Future<Void> o Future<?> o solo Future

+0

se non è quello che penso, come posso essere sicuro, che tutti i thread sono stati fatti? – fen1ksss

+0

Si aggiungono * tasks * a un pool di thread, * non * thread poiché il pool di thread ha già i thread. Se si aggiunge una discussione a un pool di thread, essa non sarà nemmeno 'start()' loro perché si aspetta Runnables. –

+0

MyThread è solo una classe, questa non è una discussione – fen1ksss

1

inizializzare un controllo variabile value = 1 e aggiornare il valore nel resto .then controllare il valore del controllo dopo il ciclo ha eseguito

 if (future.isDone()) { 
      System.out.println("true"); 
     } 
     else 
      {System.out.println("false"); 
      check=0;} 
2

L'utilizzo di una variabile booleana è il modo più semplice per comprendere che tutti i thread sono stati eseguiti. Un altro modo potrebbe essere l'utilizzo di una primitiva, ad es. un numero intero Potresti semplicemente incrementare/decrementare il contatore per vedere se tutti i thread sono stati eseguiti.

E un altro modo potrebbe verificare il valore restituito dell'impostazione awaitTermination() sull'oggetto ExecutorService.

int counter = 0; 

    for(Future<Boolean> future : futures) 
    { 
     future.get();    
     if (future.isDone()) 
      System.out.println("true"); 
     else 
     { 
      counter++; 
      System.out.println("false"); 
     } 
    } 

    if(counter != 0) 
     System.out.println("DONE!"); 

    // Another way of checking all threads are done. 
    if(executor.awaitTermination(100, TimeUnit.SECONDS)) 
     System.out.println("DONE!"); 
+0

è necessario utilizzare .get e .isDone allo stesso tempo? Se no, quale è meglio per la mia domanda? – fen1ksss

+0

@ fen1ksss get e isDone sono metodi diversi. quindi è assurdo chiedere "quale è meglio per la mia domanda?". Il modo in cui usi questi metodi sembra ok, penso. – Juvanis

+0

ok, grazie – fen1ksss

16

inteso come un commento sulla risposta di vainolo ma non hanno abbastanza punti reputazione:

isDone è anche ridondante, perché invokeAll restituisce un elenco di termine per i quali isDone è vero. Il javadocs mention this.

+1

Questa è la migliore risposta secondo me. Per chiarire, invokeAll non ritorna fino a quando non vengono completate tutte le attività, cioè sta bloccando. (Ci sono sovraccarichi che non bloccano) – Konstantin

0

Invokeall di chiamare questo metodo attende completo tutti prendono poi l'esecuzione della CPU raggiunge a ciclo for per verificare il completamento O abbiamo bisogno di fare .. While Per controllare completamento dei compiti

Problemi correlati