Question

Quelle est la différence entre utiliser un nouveau thread et utiliser un thread du pool de threads? Quels sont les avantages en termes de performances et pourquoi devrais-je envisager d'utiliser un thread du pool plutôt que celui que j'ai explicitement créé? Je pense spécifiquement à .NET ici, mais les exemples généraux sont bien.

Était-ce utile?

La solution

Le pool de threads présente des avantages pour les opérations fréquentes et relativement courtes de

.
  • Réutiliser des threads déjà créés au lieu d'en créer de nouveaux (processus coûteux)
  • Limitez le taux de création de threads lorsqu'il y a une rafale de demandes de nouveaux éléments de travail (je pense que cela ne concerne que .NET 3.5)

    • Si vous mettez en file d'attente 100 tâches de pool de threads, il utilisera uniquement le nombre de threads déjà créés pour traiter ces demandes (par exemple, 10). Le pool de threads effectuera des contrôles fréquents (toutes les 500 ms dans la version 3.5 SP1, je crois) et s’il existe des tâches en file d’attente, il créera un nouveau thread. Si vos tâches sont rapides, le nombre de nouveaux threads sera réduit et la réutilisation d'une dizaine de threads pour les tâches courtes sera plus rapide que la création de 100 threads à l'avant.

    • Si votre charge de travail reçoit régulièrement un grand nombre de demandes de pool de threads, le pool de threads s'adapte automatiquement à votre charge de travail en créant plus de threads dans le pool à l'aide du processus ci-dessus, de sorte qu'il existe un plus grand nombre de threads. disponible pour traiter les demandes

    • vérifiez Ici pour des informations plus détaillées sur le fonctionnement du pool de threads sous le capot

Créer un nouveau fil vous-même serait plus approprié si le travail devait durer assez longtemps (probablement environ une seconde ou deux, mais cela dépend de la situation spécifique)

@Krzysztof - Les threads du pool de threads sont des threads d'arrière-plan qui s'arrêteront à la fin du thread principal. Les threads créés manuellement sont au premier plan par défaut (continueront à s'exécuter une fois le thread principal terminé), mais peuvent être définis en arrière-plan avant d'appeler Démarrer sur eux.

Autres conseils

Le pool de threads géré .NET: -

  • Se redimensionne en fonction de la charge de travail actuelle et du matériel disponible
  • Contient les threads de travail et des threads de port d'achèvement (spécifiquement utilisés pour desservir IO)
  • est optimisé pour un grand nombre d'opérations de courte durée

Il existe d'autres implémentations de pool de threads qui pourraient être plus appropriées pour des opérations de longue durée.

Spécifiquement, utilisez un pool de threads pour empêcher votre application de créer trop de threads . La fonctionnalité la plus importante d'un pool de threads est la file d'attente de travail. Autrement dit, une fois que votre machine est suffisamment occupée, le pool de threads met les demandes en file d'attente plutôt que de générer immédiatement plus de threads.

Donc, si vous voulez créer un petit nombre de threads liés, créez-les vous-même. Si vous ne pouvez pas déterminer immédiatement le nombre de threads pouvant être créés (par exemple, ils sont créés en réponse à des entrées / sorties entrantes) et que leur travail sera de courte durée, utilisez le pool de threads. Si vous ne savez pas combien et que leur travail durera longtemps, rien ne vous aidera dans la plate-forme, mais vous pourrez peut-être trouver d'autres implémentations de threadpool qui vous conviennent.

aussi

  

new Thread (). Début ()

génère un thread au premier plan qui ne mourra pas si vous fermez votre programme. Les threads ThreadPool sont des threads d'arrière-plan qui meurent lorsque vous fermez l'application.

J'étais curieux de connaître l’utilisation relative de ces ressources et j’ai réalisé un test de performance sur mon ordinateur portable bicœur Intel i5 2012 à l’aide de la version .net 4.0 construite sous Windows 8. Les pools de threads prenaient en moyenne 0,035 ms pour commencer lorsque Threads moyenne de 5,06ms. En d'autres termes, le thread de la piscine a démarré environ 300 fois plus rapidement pour un grand nombre de threads de courte durée. Au moins dans la gamme testée (100-2000) de threads, le temps total par thread semblait plutôt constant.

C'est le code qui a été référencé:

    for (int i = 0; i < ThreadCount; i++) {
        Task.Run(() => { });
    }

    for (int i = 0; i < ThreadCount; i++) {
        var t = new Thread(() => { });
        t.Start();
    }

 entrez la description de l'image ici

Recherchez ici un sujet précédent:

Quand ne dois-je pas utiliser le ThreadPool dans .Net?

En résumé, Threadpool est utile si vous devez générer de nombreux threads de courte durée, alors que l'utilisation de Threads vous donne un peu plus de contrôle.

Le stockage local des threads n’est pas une bonne idée avec les pools de threads. Il donne aux threads une "identité"; tous les fils ne sont plus égaux. Maintenant, les pools de threads sont particulièrement utiles si vous avez juste besoin de plusieurs threads identiques, prêts à effectuer votre travail sans charge de création.

Si vous avez besoin de beaucoup de threads, vous voudrez probablement utiliser un ThreadPool. Ils réutilisent les threads, ce qui vous évite des frais de création de threads.

Si vous avez besoin d'un seul thread pour accomplir quelque chose, le thread est probablement le plus simple.

Le principal besoin des threads de pool est de gérer de petites tâches qui devraient s’achever presque instantanément. Les gestionnaires d'interruptions matérielles s'exécutent souvent dans un contexte d'empilement qui ne conviendrait pas pour du code non-noyau, mais un gestionnaire d'interruptions matérielles peut découvrir qu'un rappel d'achèvement des E / S en mode utilisateur doit être exécuté dès que possible. Créer un nouveau thread dans le but de faire fonctionner une telle chose serait une perte de temps énorme. Il est beaucoup plus efficace de disposer de quelques threads prédéfinis pouvant être répartis pour exécuter des rappels d’achèvement d’E / S ou d’autres tâches similaires.

Un aspect essentiel de ces threads est que, si les méthodes d’achèvement des E / S se terminent toujours de manière pratiquement instantanée et ne se bloquent jamais, et que le nombre de ces threads en cours d’exécution est au moins égal au nombre de processeurs, le seul moyen tout autre thread peut s'exécuter avant la fin de l'une des méthodes susmentionnées si l'une des autres méthodes est bloquée ou si sa durée d'exécution dépasse une tranche de temps de thread normale; aucun de ceux-ci ne devrait se produire très souvent si le pool de threads est utilisé comme prévu.

Si une méthode ne peut pas se terminer dans un délai de 100 ms environ après le début de son exécution, elle doit être exécutée par un autre moyen que le pool de threads principal. Si vous devez effectuer beaucoup de tâches nécessitant beaucoup de ressources en processeur mais ne bloquant pas, il peut être utile de les répartir à l’aide d’un pool de threads d’application (un par cœur de processeur), qui est distinct de la commande "principale". pool de threads, car utiliser plus de threads que de cœurs sera contre-productif lors de l'exécution de tâches gourmandes en ressources processeur non bloquantes. Si, toutefois, une méthode prend une seconde ou plus à s'exécuter et passe le plus clair de son temps à être bloquée, elle doit probablement être exécutée dans un thread dédié et ne devrait presque certainement pas être exécutée dans un thread principal. Si une opération de longue durée doit être déclenchée par quelque chose comme un rappel d'E / S, vous devez soit démarrer un thread pour l'opération de longue durée avant le rappel et le laisser attendre sur un moniteur dont le rappel est pulsé, ou bien demandez au callback de lancer un nouveau thread pour effectuer l'opération en même temps que le callback, renvoyant ainsi son propre thread au pool de threads.

En général (je n'ai jamais utilisé .NET), un pool de threads serait utilisé à des fins de gestion des ressources. Cela permet de configurer des contraintes dans votre logiciel. Cela peut également être fait pour des raisons de performances, car la création de nouveaux threads peut être coûteuse.

Il peut également y avoir des raisons spécifiques au système. En Java (encore une fois, je ne sais pas si cela s’applique à .NET), le responsable des threads peut appliquer des variables spécifiques aux threads à mesure que chaque thread est extrait du pool et les désélectionner lorsqu’ils sont renvoyés (moyen courant de transmettre une identité).

Exemple de contrainte: Comme je n’ai que 10 connexions à la base de données, je n’autoriserais que 10 unités de travail à accéder à la base de données.

Cela ne signifie pas que vous ne devez pas créer vos propres threads, mais il existe des conditions dans lesquelles il est logique d'utiliser un pool.

Utiliser un pool est une bonne idée si vous ne savez pas ou ne pouvez pas contrôler le nombre de threads créés.

Vous avez juste un problème avec un formulaire qui utilise thread pour mettre à jour un champ d’une base de données lors d’un événement de changement de position d’un contrôle de liste (éviter le gel). Il a fallu 5 minutes à mon utilisateur pour obtenir une erreur de la base de données (trop de connexions avec Access) car il changeait trop rapidement la position de la liste ...

Je sais qu'il existe un autre moyen de résoudre le problème de base (y compris le fait de ne pas utiliser l'accès), mais le pooling est un bon début.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top