web-dev-qa-db-fra.com

Comment vérifier si toutes les tâches exécutées sur ExecutorService sont terminées

J'ai obtenu ConcurrentLinkedDeque que j'utilise pour les éléments push/pop synchronisés, et j'ai des tâches asynchrones qui prennent un élément de la pile et si cet élément a des voisins, il le pousse vers la pile.

Exemple de code:

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)
                }
             } 
         }
    }

Je voudrais avoir une déclaration supplémentaire dans la boucle while qui répond à la question - "n'importe quelle tâche dans Executor fonctionne?"

24
user4129715

Il n'y a pas de moyen propre de vérifier si tous les Runnables sont terminés si vous utilisez ExecutorService.execute(Runnable). Sauf si vous construisez un mécanisme pour le faire dans le Runnable lui-même (ce qui est bâclé à mon avis).

Au lieu de cela:
Utilisez ExecutorService.submit(Runnable). Cette méthode renverra un Future<?> qui est un descripteur du résultat d'un Runnable. Utiliser Futures fournit un moyen propre de vérifier les résultats.

Tout ce que vous avez à faire est de maintenir une liste des contrats à terme que vous soumettez, puis vous pouvez parcourir toute la liste des contrats à terme et soit:
A) attendre que tous les contrats à terme se fassent de manière bloquante ou
B) vérifier si tous les contrats à terme se font de manière non bloquante.

Voici un exemple de code:

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
}
54
Andy Guibert