Java Language Attendez la fin de toutes les tâches dans ExecutorService


Exemple

Jetons un coup d'oeil aux différentes options pour attendre l'achèvement des tâches soumises à l' exécuteur

  1. ExecutorService invokeAll()

    Exécute les tâches données, en retournant une liste de contrats à terme conservant leur statut et leurs résultats lorsque tout est terminé.

Exemple:

import java.util.concurrent.*;
import java.util.*;

public class InvokeAllDemo{
    public InvokeAllDemo(){
        System.out.println("creating service");
        ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        
        List<MyCallable> futureList = new ArrayList<MyCallable>();
        for (int i = 0; i < 10; i++){
            MyCallable myCallable = new MyCallable((long)i);
            futureList.add(myCallable);
        }
        System.out.println("Start");
        try{
            List<Future<Long>> futures = service.invokeAll(futureList);  
        } catch(Exception err){
            err.printStackTrace();
        }
        System.out.println("Completed");
        service.shutdown();
    }
    public static void main(String args[]){
        InvokeAllDemo demo = new InvokeAllDemo();
    }
    class MyCallable implements Callable<Long>{
        Long id = 0L;
        public MyCallable(Long val){
            this.id = val;
        }
        public Long call(){
            // Add your business logic
            return id;
        }
    }
}
  1. CountDownLatch

    Une aide à la synchronisation qui permet à un ou plusieurs threads d'attendre qu'un ensemble d'opérations soit exécuté dans d'autres threads.

    Un CountDownLatch est initialisé avec un nombre donné. Les méthodes d’attente bloquent jusqu’à ce que le nombre actuel atteigne zéro en raison des countDown() méthode countDown() , après quoi tous les threads en attente sont libérés et toutes les invocations d’attente suivantes sont countDown() immédiatement. Ceci est un phénomène à un coup - le compte ne peut pas être réinitialisé. Si vous avez besoin d'une version qui réinitialise le compte, envisagez d'utiliser un CyclicBarrier .

  2. ForkJoinPool ou newWorkStealingPool() dans les exécuteurs

  3. Parcourez tous les objets Future créés après la soumission à ExecutorService

  4. Méthode recommandée pour arrêter la page de documentation d'Oracle d' ExecutorService :

    void shutdownAndAwaitTermination(ExecutorService pool) {
        pool.shutdown(); // Disable new tasks from being submitted
        try {
          // Wait a while for existing tasks to terminate
          if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
            pool.shutdownNow(); // Cancel currently executing tasks
            // Wait a while for tasks to respond to being cancelled
            if (!pool.awaitTermination(60, TimeUnit.SECONDS))
                System.err.println("Pool did not terminate");
          }
        } catch (InterruptedException ie) {
          // (Re-)Cancel if current thread also interrupted
          pool.shutdownNow();
          // Preserve interrupt status
          Thread.currentThread().interrupt();
        }
    

    shutdown(): lance un arrêt ordonné au cours duquel les tâches précédemment soumises sont exécutées, mais aucune nouvelle tâche ne sera acceptée.

    shutdownNow(): tente d'arrêter toutes les tâches en cours d'exécution, arrête le traitement des tâches en attente et renvoie une liste des tâches en attente d'exécution.

    Dans l'exemple ci-dessus, si vos tâches prennent plus de temps, vous pouvez changer si condition à condition

    Remplacer

    if (!pool.awaitTermination(60, TimeUnit.SECONDS))
    

    avec

    while(!pool.awaitTermination(60, TimeUnit.SECONDS)) {
      Thread.sleep(60000);
    

    }