Quand dois-je utiliser un CompletionService sur un ExecutorService?
Je viens de trouver CompletionService dans ce blog. Cependant, ce n'est pas vraiment présente les avantages de CompletionService sur une norme ExecutorService. Le même code peut être écrit avec les deux. Donc, quand on est un CompletionService utile?
Pouvez-vous donner un court exemple de code pour faire ce cristal clair? Par exemple, cet exemple de code montre où un CompletionService n'est pas nécessaire (=équivalent à ExecutorService)
ExecutorService taskExecutor = Executors.newCachedThreadPool();
// CompletionService<Long> taskCompletionService =
// new ExecutorCompletionService<Long>(taskExecutor);
Callable<Long> callable = new Callable<Long>() {
@Override
public Long call() throws Exception {
return 1L;
}
};
Future<Long> future = //taskCompletionService.submit(callable);
taskExecutor.submit(callable);
while (!future.isDone()) {
//Do some work...
System.out.println("Working on something...");
}
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
Vous devez vous connecter pour publier un commentaire.
Avec
ExecutorService
, une fois que vous avez soumis les tâches à exécuter, vous devez coder manuellement efficacement pour obtenir les résultats des tâches accomplies.Avec
CompletionService
, c'est à peu près automatisé. La différence n'est pas très évidente dans le code que vous avez présenté, parce que vous soumettez à une seule tâche. Cependant, imaginez que vous avez une liste de tâches à être soumis. Dans l'exemple ci-dessous, plusieurs tâches sont soumis à la CompletionService. Alors, au lieu d'essayer de savoir quelle tâche est terminée (pour obtenir les résultats), il demande juste le CompletionService exemple pour renvoyer les résultats à mesure qu'ils deviennent disponibles.take
etpoll
sur CompletionService sont thread-safe? Dans votre exemple, les tâches sont toujours en cours d'exécution lors de la première invoquertake()
, et je ne vois pas du tout explicite de la synchronisation.take()
est en effet thread-safe. Vous pouvez le lire dans la Javadoc, mais, fondamentalement,take()
va attendre la prochaine terminé résultat et puis retour. LeCompletionService
fonctionne avec unBlockingQueue
pour la sortie.En omettant de nombreux détails:
Je pense que la javadoc meilleures réponses à la question de savoir quand la
CompletionService
est utile dans un façon uneExecutorService
ne l'est pas.Fondamentalement, cette interface permet à un programme de disposer de producteurs qui créer et soumettre des tâches (et même examiner les résultats de ces moyens) sans savoir à propos de tous les autres consommateurs, les résultats de ces tâches. Pendant ce temps, les consommateurs qui sont conscients de la
CompletionService
pourraitpoll
outake
résultats sans être au courant des producteurs de soumettre les tâches.Pour l'enregistrement, et j'ai peut-être tort, car il est un peu tard, mais je suis assez certain que le code d'exemple dans ce billet de blog provoque une fuite de mémoire. Sans un consommateur actif prenant les résultats de la
ExecutorCompletionService
internes de la file d'attente, je ne suis pas sûr de savoir comment le blogueur attend à ce que la file d'attente à l'égout.Fondamentalement, vous utilisez un
CompletionService
si vous voulez exécuter plusieurs tâches en parallèle, et ensuite travailler avec eux dans leurs achèvement de la commande. Donc, si j'execute 5 emplois, laCompletionService
me donnera la première que cela se termine. L'exemple où il n'existe qu'une seule tâche ne confère aucune valeur supplémentaire sur uneExecutor
outre la possibilité de soumettre unCallable
.Tout d'abord, si nous ne voulez pas gaspiller de temps processeur, nous n'utiliserons pas
Nous devons utiliser
La mauvaise chose à propos de ce code est qu'il va fermer
ExecutorService
. Si nous voulons continuer à travailler avec elle (c'est à dire que nous avons une certaine recursicve la création de la tâche), nous avons deux solutions: invokeAll ouExecutorService
.invokeAll
va attendre jusqu'à ce que tous les tâches à remplir.ExecutorService
nous donne la capacité de prendre ou de résultats d'un sondage, un par un.Et, finily, récursive exemple:
Voir par vous-même au moment de l'exécution,essayez de mettre en œuvre des solutions (Executorservice et Completionservice) et vous verrez comment les différents qu'ils se comportent et ce sera plus clair quand utiliser l'un ou l'autre.
Il y a un exemple ici si vous voulez http://rdafbn.blogspot.co.uk/2013/01/executorservice-vs-completionservice-vs.html
Disons que vous avez 5 long de la tâche en cours d'exécution(callable tâche) et que vous avez soumis ces tâches à l'exécuteur de service. Maintenant, imaginez que vous ne voulez pas attendre pour l'ensemble des 5 tâche de concourir au lieu de cela, vous voulez faire une sorte de traitement de ces tâches si tout se termine. Maintenant, cela peut être fait soit par écrit logique d'interrogation sur l'avenir des objets ou de l'utilisation de cette API.
il est un autre avantage de l'utilisation de completionservice: Performance
lorsque vous appelez
future.get()
, vous êtes spin attente:de
java.util.concurrent.CompletableFuture
quand vous avez un travail de longue haleine, ce sera une catastrophe pour la performance.
avec completionservice, une fois que la tâche est terminée, il est le résultat sera mis en attente et vous pouvez interrogation de la file d'attente à faible rendement plat.
completionservice y parvenir en utilisant l'écharpe tâche avec une
done
crochet.java.util.concurrent.ExecutorCompletionService
Si la tâche du producteur n'est pas intéressé par les résultats et il est une autre composante de la responsabilité pour les résultats du processus de tâche asynchrone exécuté par l'exécuteur de service, alors vous devriez utiliser CompletionService. Il vous aide dans la séparation des tâches résultat processeur de la tâche de producteur. Voir l'exemple http://www.zoftino.com/java-concurrency-executors-framework-tutorial
=======================================================
===========================================================
======================================================================
différence de journaux pour exécuteur testamentaire de l'achèvement du service:
le thread courant est pool-1-thread-1, le résultat devrait être de 1
le thread courant est pool-1-thread-2 le résultat devrait être de 2
le thread courant est pool-1-thread-3 le résultat devrait être de 3
le thread courant est pool-1-thread-4 le résultat devrait être de 4
le thread courant est pool-1-thread-6 le résultat devrait être de 6
le thread courant est pool-1-thread-5 le résultat doit être de 5
le thread courant est pool-1-thread-7 le résultat devrait être de 7
le thread courant est pool-1-thread-9 le résultat doit être de 9
le thread courant est pool-1-thread-8 le résultat devrait être de 8
la tâche complted pour pool-1-thread-9 le résultat doit être de 9
le résultat est 9
la tâche complted pour pool-1-thread-8 le résultat devrait être de 8
la tâche complted pour pool-1-thread-7 le résultat devrait être de 7
la tâche complted pour pool-1-thread-6 le résultat devrait être de 6
la tâche complted pour pool-1-thread-5 le résultat doit être de 5
la tâche complted pour pool-1-thread-4 le résultat devrait être de 4
la tâche complted pour pool-1-thread-3 le résultat devrait être de 3
la tâche complted pour pool-1-thread-2 le résultat devrait être de 2
le thread courant est pool-1-thread-1, le résultat devrait être de 1
le thread courant est pool-1-thread-3 le résultat devrait être de 3
le thread courant est pool-1-thread-2 le résultat devrait être de 2
le thread courant est pool-1-thread-5 le résultat doit être de 5
le thread courant est pool-1-thread-4 le résultat devrait être de 4
le thread courant est pool-1-thread-6 le résultat devrait être de 6
le thread courant est pool-1-thread-7 le résultat devrait être de 7
le thread courant est pool-1-thread-8 le résultat devrait être de 8
le thread courant est pool-1-thread-9 le résultat doit être de 9
la tâche complted pour pool-1-thread-9 le résultat doit être de 9
la tâche complted pour pool-1-thread-8 le résultat devrait être de 8
la tâche complted pour pool-1-thread-7 le résultat devrait être de 7
la tâche complted pour pool-1-thread-6 le résultat devrait être de 6
la tâche complted pour pool-1-thread-5 le résultat doit être de 5
la tâche complted pour pool-1-thread-4 le résultat devrait être de 4
la tâche complted pour pool-1-thread-3 le résultat devrait être de 3
la tâche complted pour pool-1-thread-2 le résultat devrait être de 2
la tâche complted pour pool-1-thread-1, le résultat devrait être de 1
le résultat de l'avenir est 1
=======================================================
pour executorservice le résultat ne sera disponible une fois toutes les tâches complted.
exécuteur completionservice aucun résultat disponible faire ce retour.