Quels sont les avantages d'utiliser un ExecutorService?

Quel est l'avantage d'utiliser ExecutorService au-dessus des fils courants passant un Runnable dans le constructeur Thread ?

39
demandé sur andersoj 2010-10-21 07:31:06

8 réponses

ExecutorService résume bon nombre des complexités associées aux abstractions de niveau inférieur comme le Thread brut . Il fournit des mécanismes pour démarrer, fermer, soumettre, exécuter et bloquer en toute sécurité sur la fin réussie ou abrupte des tâches (exprimé comme Runnable ou Callable ).

à Partir de JCiP , Section 6.2, directement de la bouche des chevaux:

Executor peut être un interface simple, mais elle forme la base d'un cadre souple et puissant pour l'exécution asynchrone des tâches qui soutient une grande variété de politiques d'exécution des tâches. Il fournit un moyen standard de découplage task submission de task execution , décrivant les tâches comme Runnable . Les implémentations Executor fournissent également un support du cycle de vie et des hooks pour ajouter la collecte de statistiques, la gestion d'applications et la surveillance. ... L'utilisation d'un Executor est habituellement la façon la plus facile de mettre en œuvre un dessin ou modèle producteur-consommateur dans votre application.

plutôt que de passer votre temps à mettre en œuvre (souvent incorrectement, et avec beaucoup d'efforts) l'infrastructure sous-jacente du parallélisme, le cadre j.u.concurrent vous permet de vous concentrer sur la structuration des tâches, des dépendances, du parallélisme potentiel. Pour une grande parcelle de demandes concurrentes, il est simple de identifiez et exploitez les limites des tâches et utilisez j.u.c , vous permettant de vous concentrer sur le sous-ensemble beaucoup plus petit de véritables défis de concurrence qui peuvent nécessiter des solutions plus spécialisées.

en outre, malgré l'apparence boilerplate, la page de L'API Oracle résumant les utilitaires de concurrence comprend des arguments vraiment solides pour les utiliser, notamment:

développeurs sont susceptibles de déjà comprendre la bibliothèque standard les cours, donc il n'y a pas besoin d'apprendre L'API et le comportement de ad-hoc composants concurrents. Outre, les applications concurrentes sont loin plus simple à déboguer quand ils sont construits sur fiable, bien des composants testés.

Ce question DONC , demande un bon livre, dont la réponse immédiate est JCiP. Si vous ne l'avez pas déjà fait, procurez-vous une copie. L'approche globale de la la concurrence présentée ici va bien au-delà de cette question, et vous sauvera beaucoup de chagrin à long terme.

39
répondu andersoj 2017-05-23 10:31:37

un avantage que je vois est dans la gestion/programmation de plusieurs threads. Avec ExecutorService, vous n'avez pas à écrire votre propre gestionnaire de threads qui peut être harcelé par des bogues. Ceci est particulièrement utile si votre programme doit exécuter plusieurs threads à la fois. Par exemple, vous voulez exécuter deux threads à la fois, vous pouvez facilement le faire comme ceci:

ExecutorService exec = Executors.newFixedThreadPool(2);

exec.execute(new Runnable() {
  public void run() {
    System.out.println("Hello world");
  }
});

exec.shutdown();

l'exemple peut être trivial, mais essayez de penser que la ligne" hello world " consiste en une opération lourde et vous voulez que cette opération s'exécute en plusieurs threads à la fois afin d'améliorer les performances de votre programme. Ce n'est qu'un exemple, il y a encore de nombreux cas où vous voulez programmer ou exécuter plusieurs threads et utiliser ExecutorService comme votre gestionnaire de threads.

pour exécuter un seul thread, Je ne vois aucun avantage évident à utiliser ExecutorService.

18
répondu Manny 2010-10-21 05:36:42

ci-dessous sont quelques avantages:

  1. Exécuteur testamentaire service à gérer thread de manière asynchrone
  2. utilisez callable pour obtenir le résultat de retour après l'achèvement du thread.
  3. Gérer l'attribution du travail au filetage libre et la revente du travail terminé à partir du filetage pour attribuer automatiquement un nouveau travail
  4. fork - join-cadre pour le traitement en parallèle
  5. meilleure communication entre les fils
  6. invokeAll et invokeAny donner plus de contrôle à exécuter tout ou thread à la fois
  7. l'arrêt de fournir des capacités pour l'achèvement de tous les threads de travail assigné
  8. Prévue Exécuteur des Services de fournir des méthodes pour la production de répéter les invocations de runnables et callables Espérons, vous aidera à
8
répondu Nitin 2013-07-01 08:01:06

les limitations suivantes du Thread traditionnel surmontées par Executor framework(built-in Thread Pool framework).

  • la Mauvaise Gestion des Ressources c'est à dire de tenir sur la création de nouvelles ressources pour chaque demande. Aucune limite à la création de ressources. En utilisant Executor framework, nous pouvons réutiliser les ressources existantes et limiter la création de ressources.
  • pas robuste : si nous continuons à créer de nouveaux le fil nous aurons StackOverflowException exception par conséquent, à notre JVM en panne.
  • création de temps : pour chaque demande, nous devons créer de nouvelles ressources. La création de nouvelles ressources prend du temps. c'est à dire de Threads Création d' > tâche. En utilisant Executor framework nous pouvons être construits dans Thread Pool.

avantages du pool de fils

  • utilisation de fils Pool réduit le temps de réponse en évitant la création de thread pendant le traitement des requêtes ou des tâches.

  • L'utilisation de Thread Pool vous permet de modifier votre politique d'exécution comme vous le souhaitez. vous pouvez passer d'un thread simple à plusieurs threads en remplaçant simplement L'implémentation D'ExecutorService.

  • Thread Pool dans L'application Java augmente la stabilité du système en créant un nombre configuré de threads décidé sur la base du système charge et ressources disponibles.

  • Thread Pool libère le développeur d'applications des trucs de gestion de thread et permet de se concentrer sur la logique d'affaires.

Source

7
répondu Premraj 2015-12-19 11:21:51

est-ce vraiment si cher de créer un nouveau fil?

comme benchmark, je viens de créer 60 000 threads avec Runnable s avec des méthodes vides run() . Après avoir créé chaque thread, j'ai immédiatement appelé sa méthode start(..) . Cela a pris environ 30 secondes d'intense activité CPU. Des expériences similaires ont été faites en réponse à cette question . Le résumé de ceux - ci est que si les fils ne finissent pas immédiatement, et une grande nombre de threads actifs s'accumulent (quelques milliers), puis il y aura des problèmes: (1) chaque thread a une pile, donc vous manquerez de mémoire, (2) il pourrait y avoir une limite sur le nombre de threads par processus imposé par L'OS, mais pas nécessairement, il semble .

donc, autant que je puisse voir, si nous parlons de lancer disons 10 threads par seconde, et ils finissent tous plus vite que les nouveaux commencent, et nous pouvons garantir que ce taux ne sera pas dépassé trop, alors L'Exécutorservice n'offre aucun avantage concret en termes de performances visibles ou de stabilité. (Bien qu'il puisse encore être plus pratique ou plus lisible d'exprimer certaines idées de concurrence en code. D'un autre côté, si vous planifiez des centaines ou des milliers de tâches par seconde, qui prennent du temps à exécuter, vous pourriez rencontrer de gros problèmes tout de suite. Cela peut se produire de manière inattendue, par exemple si vous créez des threads en réponse à des requêtes vers un serveur, et qu'il y a un pic dans le intensité des requêtes que votre serveur reçoit. Mais par exemple, un thread en réponse à chaque événement d'entrée utilisateur (touche press, mouvement de la souris) semble parfaitement correct, tant que les tâches sont brèves.

2
répondu Evgeni Sergeev 2017-05-23 12:18:24

ExecutorService donne également accès à FutureTask qui retournera à la classe calling les résultats d'une tâche de fond une fois terminée. Dans le cas de la mise en œuvre appelable

public class TaskOne implements Callable<String> {

@Override
public String call() throws Exception {
    String message = "Task One here. . .";
    return message;
    }
}

public class TaskTwo implements Callable<String> {

@Override
public String call() throws Exception {
    String message = "Task Two here . . . ";
    return message;
    }
}

// from the calling class

ExecutorService service = Executors.newFixedThreadPool(2);
    // set of Callable types
    Set<Callable<String>>callables = new HashSet<Callable<String>>();
    // add tasks to Set
    callables.add(new TaskOne());
    callables.add(new TaskTwo());
    // list of Future<String> types stores the result of invokeAll()
    List<Future<String>>futures = service.invokeAll(callables);
    // iterate through the list and print results from get();
    for(Future<String>future : futures) {
        System.out.println(future.get());
    }
1
répondu Bade 2015-07-08 10:02:26

avant la version java 1.5, Thread / Runnable a été conçu pour deux services séparés

  1. Unité de travail
  2. exécution de cette unité de travail

ExecutorService dissocie ces deux services en désignant Exécutable/Appelable comme unité de travail et l'exécutant en tant que mécanisme d'exécution ( avec lifecycling) à l'unité de travail

0
répondu Anil Saha 2015-02-13 04:59:22

la création d'un grand nombre de threads sans restriction au seuil maximum peut causer l'application de manquer de mémoire tas. A cause de cela, créer un ThreadPool est une bien meilleure solution. En utilisant ThreadPool nous pouvons limiter le nombre de threads qui peuvent être regroupés et réutilisés.

Exécuteurs cadre faciliter le processus de création de pools de Threads en java. La classe Executors fournit une implémentation simple D'ExecutorService en utilisant ThreadPoolExecutor.

Source:

qu'est-Ce que les Exécuteurs Cadre

0
répondu Aftab Virtual 2018-06-18 16:07:28