web-dev-qa-db-fra.com

Filetage simple SingleThreadExecutor VS

Outre le fait que l'interface Executor présente certains avantages par rapport aux threads simples (gestion, par exemple), existe-t-il une réelle différence interne (grande différence de performances, consommation de ressources ...) entre faire:

ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(runnable);

Et:

Thread thread = new Thread(runnable);
thread.start();

Je ne demande qu'un seul fil ici.

16
Magd Kudama

Executors # newSingleThreadExecutor () crée ThreadPoolExecutor objet sous le capot,
voir le code ici: http://www.docjar.com/html/api/Java/util/concurrent/Executors.Java.html

  133       public static ExecutorService newSingleThreadExecutor() {
  134           return new FinalizableDelegatedExecutorService
  135               (new ThreadPoolExecutor(1, 1,
  136                                       0L, TimeUnit.MILLISECONDS,
  137                                       new LinkedBlockingQueue<Runnable>()));
  138       }

Le documentation de ThreadPoolExecutor explique dans quelles situations il offre des avantages:

Les pools de threads résolvent deux problèmes différents: ils fournissent généralement de meilleures performances lors de l'exécution d'un grand nombre de tâches asynchrones , en raison de la réduction de la charge d'appel par tâche, et ils fournissent un moyen de délimiter et de gérer les ressources, y compris les threads, consommées lors de l'exécution d'une collection de tâches. Chaque ThreadPoolExecutor conserve également des statistiques de base, telles que le nombre de tâches terminées.

Si tout ce dont vous avez besoin est d'exécuter un seul thread de temps en temps (disons une fois par heure), alors en termes de performances, l'utilisation de ThreadPoolExecutor peut être plus lente, car vous devez instancier l'ensemble de la machine (pool + fil), puis jetez-le de la mémoire.

Mais si vous souhaitez utiliser ce thread unique souvent (disons toutes les 15 secondes), l'avantage est que vous ne créez le pool et le thread qu'une seule fois , en conservant en mémoire, et utilisez-le tout le temps pour gagner du temps en créant un nouveau fil de temps en temps (ce qui peut être assez cher, si vous voulez l'utiliser, disons toutes les 15 secondes environ).

8
krokodilko

C'est une abstraction et celles-ci ont toujours un "coût":

  • un certain montant (potentiel) de "pénalité de performance"
  • une quantité réduite de "contrôle" (c'est tout l'intérêt - vous n'avez pas besoin de vous occuper des détails de bas niveau, donc, si vous le deviez, ...)

La principale différence est que le service vous permet de soumettre des tâches multiples, tandis que le thread peut exécuter exactement un Runnable. D'un autre côté, vous devez vous soucier de choses telles que "fermer" le service.

Une règle d'or: les aspects liés aux performances devraient être ici presque "ignorables". Pour cette raison, vous préférez la solution de service exécuteur "plus abstraite". Parce que cela vous permet de séparer vos préoccupations du filetage réel. Et plus important encore: si vous choisissez d'utiliser un type d'implémentation différent pour ce service ... le reste de votre code ne devrait pas avoir à s'en soucier.

Pour faire court: les abstractions coûtent, mais dans ce cas, vous préférez généralement la solution "plus abstraite". Parce qu'au final, cela réduit la complexité de votre solution.

2
GhostCat

La principale différence réside dans la politique d'exécution des tâches.

En créant une instance de Thread ou en sous-classant Thread, vous exécutez essentiellement une seule tâche.

En revanche, l'utilisation de Executors.newSingleThreadExecutor() vous permet de soumettre plusieurs tâches. Étant donné que ces tâches sont garanties pas pour être exécutées simultanément, cela vous permet d'exploiter les avantages suivants confinement de thread :

  • Aucune synchronisation requise lors de l'accès à des objets qui ne sont pas thread-safe
  • Les effets de mémoire d'une tâche sont garantis pour être visibles à la tâche suivante
0
xuesheng

Si vous n'avez qu'un Runnable à exécuter, alors il y a pas de grande différence entre eux.

L'utilisation de thread simple peut être un peu plus efficace car la création d'un ExecutorService tel que ThreadPoolExecutor a autre chose à faire que de créer un nouveau thread. Par exemple, créer une file d'attente de blocage, créer une politique, bien que ces choses se fassent implicitement.

Et vous devez shutdown l'exécuteur après l'exécution de ce runnable. Sinon, le thread unique de ce pool ne se fermera jamais.

0
xingbin