ExecutorService vs Casual Fil des Reproducteurs
J'ai une question de base sur la façon ExecutorService
fonctionne en Java.
Il est assez difficile de voir la différence entre la création d' Threads
pour effectuer certaines tâches en parallèle et en attribuant à chacun des tâches à l' ThreadPool
.
La ExecutorService
l'air également très simple à utiliser et efficace, alors je me demandais pourquoi nous n'utilisons pas tout le temps.
Est-ce juste une question de façon de l'exécution de son travail plus vite que les autres ?
Voici deux exemples très simples pour montrer la différence entre les deux façons :
À l'aide de l'exécuteur de service: Bonjour tout le Monde (tâche)
static class HelloTask implements Runnable {
String msg;
public HelloTask(String msg) {
this.msg = msg;
}
public void run() {
long id = Thread.currentThread().getId();
System.out.println(msg + " from thread:" + id);
}
}
À l'aide de l'exécuteur de service: Bonjour tout le Monde (la création d'exécuteur testamentaire, l'envoi)
static class HelloTask {
public static void main(String[] args) {
int ntasks = 1000;
ExecutorService exs = Executors.newFixedThreadPool(4);
for (int i=0; i<ntasks; i++) {
HelloTask t = new HelloTask("Hello from task " + i);
exs.submit(t);
}
exs.shutdown();
}
}
la figure suivante montre un exemple similaire, mais qui s'étend le Callable interface, pourriez-vous me dire la différence entre les deux et dans quels cas on doit utiliser un spécifique à la place de l'autre ?
À l'aide de l'exécuteur de service: Comptoir (tâche)
static class HelloTaskRet implements Callable<Long> {
String msg;
public HelloTaskRet(String msg) {
this.msg = msg; }
public Long call() {
long tid = Thread.currentThread().getId();
System.out.println(msg + " from thread:" + tid);
return tid;
}
}
À l'aide de l'exécuteur de service: (la création, la soumission)
static class HelloTaskRet {
public static void main(String[] args) {
int ntasks = 1000;
ExecutorService exs = Executors.newFixedThreadPool(4);
Future<Long>[] futures = (Future<Long>[]) new Future[ntasks];
for (int i=0; i<ntasks; i++) {
HelloTaskRet t = new HelloTaskRet("Hello from task " + i);
futures[i] = exs.submit(t);
}
exs.shutdown();
}
}
ExecutorService
au lieu de créer de nouveaux Threads, donc je ne suis pas sûr de ce que vous êtes de la comparaison entre les 2 exemples dans ce cas. Est votre confusion sur l'utilisation de Runnable
et quand utiliser Callable
?OriginalL'auteur Phil Moesch | 2014-11-14
Vous devez vous connecter pour publier un commentaire.
Alors que la question et l'exemple de code ne sont pas corrélés, je vais essayer de clarifier les deux.
L'avantage de
ExecutorService
plus au hasard de frai threads, c'est qu'il se comporte de manière prévisible et évite la surcharge de création de thread, ce qui est relativement grand sur la JVM (il a besoin de réserver de la mémoire pour chaque thread, par exemple). Par la prévisibilité, au moins pour lefixedThreadPool
, je veux dire que vous savez le nombre maximal de threads simultanés, et vous savez quand et comment ils pourraient se créé (si votre JVM ne pas exploser en cas de brusques pics).Maintenant, sur le sujet de la
Runnable
vsCallable
, il est facile de voir à partir de votre exemple.Callable
s peut retourner une valeur à la place de titulaire (Future
) qui finiront par être remplis par une valeur réelle dans le futur.Runnable
s ne peut pas retourner quoi que ce soit.OriginalL'auteur kaqqao
ExecutorService offre de nombreux avantages par rapport à la plaine de threads
Même pour un seul Thread, je préfère utiliser
Executors.newFixedThreadPool(1);
Regarder liées SE questions:
Java Fork/Join vs ExecutorService - quand à utiliser?
Quels sont les avantages de l'utilisation d'un ExecutorService?
OriginalL'auteur Ravindra babu