Redimensionnement dynamique de java.util.de façon concomitante.ThreadPoolExecutor alors qu'elle a des tâches en attente
Je travaille avec un java.util.concurrent.ThreadPoolExecutor
pour traiter un certain nombre d'éléments en parallèle. Bien que le thread lui-même fonctionne très bien, à certains moments, nous avons exécuté dans d'autres contraintes en matière de ressources en raison des actions qui se passe dans les threads, ce qui nous a amenés à vouloir composer le nombre de Threads dans la piscine.
Je voudrais savoir si il existe un moyen de composer le numéro du fils, tout les fils sont en fait de travail. Je sais que vous pouvez appeler setMaximumPoolSize()
et/ou setCorePoolSize()
, mais ces seuls redimensionner la piscine une fois que les threads devenu inactif, mais ils ne deviennent pas inactif jusqu'à ce qu'il n'y a pas de tâches en attente dans la file d'attente.
OriginalL'auteur Edward Shtern | 2010-05-07
Vous devez vous connecter pour publier un commentaire.
Autant que je peux dire, ce n'est pas possible, dans un agréable et très propre.
Vous pouvez mettre en œuvre la beforeExecute méthode de vérification de certains boolean valeur et de la force de threads pour arrêter temporairement. Gardez à l'esprit, elles contiennent une tâche qui ne sera pas exécuté jusqu'à ce qu'ils sont réactivées.
Alternativement, vous pouvez mettre en œuvre afterExecute pour lancer une RuntimeException lorsque vous sont saturés. Cela aura pour effet de provoquer le Fil de mourir et depuis le Liquidateur sera au-dessus du max, pas de nouvelle serait créée.
Je ne vous recommande pas de le faire. Au lieu de cela, essayez de trouver un autre moyen de contrôle concomitant de l'exécution des tâches qui sont à l'origine un problème pour vous. Éventuellement par de les exécuter dans un thread séparé de la piscine avec un nombre plus restreint de travailleurs.
OriginalL'auteur Tim Bender
Vous ne pouvez absolument. L'appel de
setCorePoolSize(int)
va changer la taille du noyau de la piscine. Les appels à cette méthode sont thread-safe et remplacer les paramètres fournis par le constructeur deThreadPoolExecutor
. Si vous êtes ajustement de la taille du pool, les autres threads d'arrêt une fois que leur travail actuel de la file d'attente est terminé (si ils sont inactifs, ils seront à l'arrêt immédiatement). Si vous augmentez la taille du pool, de nouvelles discussions seront attribués dès que possible. Le délai pour l'attribution de nouveaux threads est sans-papiers—, mais dans la mise en œuvre, l'attribution de nouveaux threads est effectuée lors de chaque appel à laexecute
méthode.De paire avec un runtime-accordable travail à la ferme, vous pouvez exposer cette propriété (soit par du papier d'emballage ou à l'aide d'un MBean dynamique de l'exportateur) en lecture-écriture JMX attribut pour créer un plutôt agréable, à la volée accordable dans le traitement par lot.
Pour réduire la taille du pool de force dans l'exécution (ce qui est de votre demande), vous devez sous-classe de la
ThreadPoolExecutor
et ajouter une perturbation de labeforeExecute(Thread,Runnable)
méthode. Interrompre le fil n'est pas suffisant interruption, depuis qu'elle n'interagit avec d'états d'attente et pendant le traitement, laThreadPoolExecutor
threads de tâche de ne pas aller dans un interruptable état.J'ai récemment eu le même problème en essayant d'obtenir un pool de threads de force à la fin avant que toutes les tâches sont exécutées. Pour ce faire, j'ai interrompu le fil en lançant une exception d'exécution seulement après le remplacement de la
UncaughtExceptionHandler
de la discussion avec l'un qui attend mon exception spécifique et les ignore.Dans votre cas, vous souhaiterez peut-être créer un sémaphore (juste pour une utilisation en tant que thread-safe compteur) ce qui n'a pas de permis, et lors de la fermeture des threads libération d'un certain nombre de permis qui correspond au delta de la précédente base de la taille du pool et de la nouvelle piscine de taille (vous demandant de remplacer le
setCorePoolSize(int)
méthode). Cela vous permettra de mettre fin à votre fils après leur tâche en cours est terminée.Cela devrait interrompre n threads pour f(n) = actif - requis. Si il y a un problème, le
ThreadPoolExecutor
s stratégie de répartition est assez durable. Livre-garde sur la fin prématurée à l'aide d'unfinally
bloc qui garantit l'exécution. Pour cette raison, même si vous résiliez trop de threads, ils vont repeupler.J'ai mis à jour mon post pour décrire une solution de dérivé d'un problème que j'ai eu récemment ce qui est semblable dans la nature. S'il vous plaît avoir un coup d'oeil.
Je ne comprends pas, pourquoi puis-je obtenir zéro karma pour répondre à cette question? 🙁
Hey Scott super réponse!! Merci
C'est une formidable réponse
OriginalL'auteur Scott S. McCoy
La solution consiste à drainer le ThreadPoolExecutor file d'attente, définir la ThreadPoolExecutor la taille que vous souhaitez, puis ajouter les filets, un par un, dès que les autres extrémités.
La méthode de vidange de la file d'attente dans le ThreadPoolExecutor classe est privé de sorte que vous avez à créer par vous-même. Voici le code:
Avant d'appeler cette méthode, vous devez obtenir, puis relâchez-le principal verrou.
Pour ce faire, vous devez utiliser java réflexion parce que le champ "mainLock" est privé.
Encore une fois, voici le code:
Où "exécuteur testamentaire" votre ThreadPoolExecutor.
Maintenant, vous devez verrouiller/déverrouiller méthodes:
Enfin, vous pouvez écrire votre "setThreadsNumber" la méthode, et il va travailler sur l'augmentation et la diminution de la ThreadPoolExecutor taille:
Remarque: évidemment, si vous exécutez N threads parallèles et la modification de ce nombre à N-1, tous les N threads continuera à s'exécuter. Lorsque le premier thread se termine pas de nouvelles discussions seront exécutées. À partir de maintenant sur le nombre de thread parallèle sera celui que vous avez choisi.
OriginalL'auteur Stefano-Davide
J'ai lu la documentation de setMaximumPoolSize() et setCorePoolSize(), et il semble qu'ils peuvent produire le comportement dont vous avez besoin.
-- EDIT --
Ma conclusion était erronée: veuillez voir la discussion ci-dessous pour plus de détails...
oui, c'est ce qu'Il dit. L'OP voulez son fils à être résilié, sans égard? Qui ne serait pas quelque chose que l'exécuteur testamentaire peut le faire même si elle le voulait. L'OP peut définir un booléen sur certaines tâches pour leur dire à la fin au début, et il serait probablement une bonne idée d'envoyer une interruption lorsque que le booléen est mis. Mais c'est l'application logique de niveau - pas de quelque chose qu'un exécuteur testamentaire pourrait le faire sortir de la main.
Un autre hasard idée serait si l'Exécuteur testamentaire pourrait limiter un certain nombre de threads par la réduction de leur priorité. Que pourrait donner le même effet d'ensemble. C'est juste un hasard de l'idée qu'il pourrait avoir d'énormes défauts que je ne suis pas d'y penser.
Jour, en fait @Eyal dit qu'ils vont mettre fin quand ils ont fini leur travail, ce n'est PAS VRAI. Ils seront récupérer une autre tâche de la file d'attente et de commencer à l'exécuter immédiatement. Si aucune tâche n'est disponible, ils vont bloquer en attente d'une tâche pour le keepAliveTime avant de finalement s'arrêter. L'OP veut les arrêter dès qu'ils sont fait avec la tâche en cours. Aussi, un travail de l'Exécuteur testamentaire est à exécuter des tâches. La gestion des Threads est le travail d'un pool de threads. Le pool de threads de la mise en œuvre pourrait avoir été, de sorte que chaque thread de travail avait pour vérifier l'autorisation de rester en vie. Mais il ne le fait PAS.
Tim Bender se résumant ma compréhension (basé sur des tests réels). -OP
OriginalL'auteur Eyal Schneider
J'étais dans un besoin pour la même solution, et il semble que dans le JDK8 setCorePoolSize() et setMaximumPoolSize() ne sont en effet de produire le résultat désiré.
J'ai fait un test dans lequel je soumettre des 4 tâches à la piscine et ils exécutent utilisées simultanément, j'ai rétrécir la taille du pool, alors qu'ils sont en cours d'exécution et de soumettre encore un autre exécutable que je veux être seul. Puis-je restaurer la piscine de revenir à sa taille d'origine. Voici le test de la source de https://gist.github.com/southerton81/96e141b8feede3fe0b8f88f679bef381
Il génère la sortie suivante (thread "50" est celui qui doit être exécutée dans l'isolement)
OriginalL'auteur southerton