2013-12-10 17 views
13

Ho una domanda da principiante. Ho questo codice:Thread.join() equivalente nell'esecutore

public class Main 
{ 

    public static void main(String[] args) throws InterruptedException 
    { 
     // TODO Auto-generated method stub 
     IntHolder aHolder=new IntHolder(); 
     aHolder.Number=0; 

     IncrementorThread A= new IncrementorThread(1, aHolder); 
     IncrementorThread B= new IncrementorThread(2, aHolder); 
     IncrementorThread C= new IncrementorThread(3, aHolder); 

     A.start(); 
     B.start(); 
     C.start(); 

     A.join(); 
     B.join(); 
     C.join(); 
     System.out.println("All threads completed..."); 

    } 

} 

Quale attenderà il completamento di tutti i thread. Se uso Executors come questo:

public class Main 
{ 

    public static void main(String[] args) 
    { 
     // TODO Auto-generated method stub 
     IntHolder aHolder=new IntHolder(); 
     aHolder.number=0; 

     IncrementalRunable A= new IncrementalRunable(1, aHolder); 
     IncrementalRunable B= new IncrementalRunable(2, aHolder); 
     IncrementalRunable C= new IncrementalRunable(3, aHolder); 

     ExecutorService exec = Executors.newFixedThreadPool(3); 
     exec.execute(A); 
     exec.execute(B); 
     exec.execute(C); 
     //Don't know what to do here 

     System.out.println("All threads completed..."); 
    } 
} 

Come posso sospendere il thread principale per attendere tutti i thread nel l'esecutore per finire, vale a dire i "Tutte le discussioni hanno completato ..." dovrebbe essere stampato dopo il tutto il le discussioni hanno fatto il loro lavoro?

+0

controllo questo: http://stackoverflow.com/questions/3269445/executorservice-how-to-wait-for-all-tasks-to-finish – giorashc

+0

Future ha aa metodo di blocco di blocco –

risposta

11
executor.shutdown(); 
while (!executor.awaitTermination(24L, TimeUnit.HOURS)) { 
    System.out.println("Not yet. Still waiting for termination"); 
} 

Usa shutdown() + awaitTermination() combinazione.

EDIT:

Sulla base del commento di @Lital

List<Callable<Object>> calls = new ArrayList<Callable<Object>>(); 
calls.add(Executors.callable(new IncrementalRunable(1, aHolder))); 
calls.add(Executors.callable(new IncrementalRunable(2, aHolder))); 
calls.add(Executors.callable(new IncrementalRunable(3, aHolder))); 

List<Future<Object>> futures = executor.invokeAll(calls); 

NOTA: invokeAll() non tornerà fino a quando tutti i compiti sono stati completati (sia omettendo o il completamento di esecuzione di successo) .

+1

Non credi che non sia una buona pratica arrestare un pool di thread solo per un semplice join? – Lital

+1

@Lital Ho aggiunto un altro approccio elegante che può essere seguito. –

+0

@NarendraPathai, ottimo, questo è ancora meglio, ma cambia i numeri per essere 1,2,3 (quelli sono i numeri di thread che uso per stampare i messaggi) –

0
exec.shutdown(); 
    // Wait until all threads are finish 
    exec.awaitTermination(); 
12

Non si dovrebbe utilizzare executor come questo se si desidera attendere il completamento delle attività. Cosa fare se non si desidera/non può arrestare l'executor del pool di thread? Questo è un modo più consigliabile:

ExecutorService exec = Executors.newFixedThreadPool(3); 
    Collection<Future<?>> tasks = new LinkedList<Future<?>>(); 

    Future<T> future = exec.submit(A); 
    tasks.add(future); 
    future = exec.submit(B); 
    tasks.add(future); 
    future = exec.submit(C); 
    tasks.add(future); 

    // wait for tasks completion 
    for (Future<?> currTask : tasks) { 
      try { 
       currTask.get(); 
      } catch (Throwable thrown) { 
       Logger.error(thrown, "Error while waiting for thread completion"); 
      } 
     } 
+0

Sono d'accordo che non dovrei usare esecutori come questo, ma sto scherzando con java ora ed ero curioso di sapere come avrei potuto –