139 votes

Impossible de créer un pool de threads mis en cache avec une limite de taille?

Il semble être impossible de faire une mise en cache du pool de threads avec une limite sur le nombre de threads qu'il peut créer.

Voici comment statique Exécuteurs testamentaires.newCachedThreadPool est mis en œuvre en Java standard de la bibliothèque:

 public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

Ainsi, l'utilisation de ce modèle pour créer un fixe mis en cache de taille du pool de threads:

new ThreadPoolExecutor(0, 3, 60L, TimeUnit.SECONDS, new SynchronusQueue<Runable>());

Maintenant, si vous utilisez ce et de soumettre des 3 tâches, tout ira bien. Soumettre d'autres tâches résultat sera rejeté l'exécution des exceptions.

Essayer ceci:

new ThreadPoolExecutor(0, 3, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runable>());

Fera en sorte que tous les threads s'exécutant de manière séquentielle. I. e., le pool de threads ne fera jamais plus d'un thread pour gérer vos tâches.

C'est un bug dans la méthode execute de ThreadPoolExecutor? Ou peut-être que c'est intentionnel? Ou il y a une autre façon?

Edit: je veux quelque chose exactement comme la mise en cache du pool de threads (il crée des threads sur la demande, puis les tue après un certain délai d'attente), mais avec une limite sur le nombre de threads qu'il peut créer et la capacité de poursuivre la file d'attente des tâches supplémentaires une fois qu'il a atteint sa limite de thread. Selon sjlee la réponse, c'est impossible. En regardant la méthode execute() de ThreadPoolExecutor il est en effet impossible. J'aurais besoin d'une classe de ThreadPoolExecutor et remplacer execute() un peu comme SwingWorker fait, mais ce que SwingWorker n'est dans ses execute() est un hack.

243voto

sjlee Points 3457

Le ThreadPoolExecutor a la suite de plusieurs comportements clés, et vos problèmes peuvent être expliquées par ces comportements.

Lorsque les tâches sont soumis,

  1. Si le pool de threads n'a pas atteint la taille du noyau, il crée de nouveaux threads.
  2. Si la taille du noyau a été atteint et il n'y a pas de threads inactifs, les files d'attente de tâches.
  3. Si la taille du noyau a été atteint, il n'y a pas de threads inactifs, et la file d'attente est pleine, elle crée de nouveaux threads (jusqu'à ce qu'il atteigne la taille max).
  4. Si la taille maximale a été atteinte, il n'y a pas de threads inactifs, et la file d'attente est pleine, le rejet de la politique des coups de pied dans.

Dans le premier exemple, note que les SynchronousQueue a essentiellement une taille de 0. Par conséquent, le moment où vous atteignez la taille maxi (3), le rejet de la politique des coups de pied dans (#4).

Dans le deuxième exemple, la file d'attente de choix est un LinkedBlockingQueue qui a une taille illimitée. Donc, vous êtes coincé avec le comportement #2.

Vous ne pouvez pas vraiment bricoler avec la mise en cache de type ou de type fixe, que leur comportement est presque entièrement déterminée.

Si vous voulez avoir délimité et dynamique pool de threads, vous devez utiliser un positif de la taille du noyau et max taille combinée avec une file d'attente d'une taille finie. Par exemple,

new ThreadPoolExecutor(10, // core size
    50, // max size
    10*60, // idle timeout
    TimeUnit.SECONDS,
    new ArrayBlockingQueue<Runnable>(20)); // queue with a size

7voto

brianegge Points 12857

Dans votre premier exemple, les tâches suivantes sont rejetés parce que le est la valeur par défaut . Le ThreadPoolExecutor contient les politiques suivantes, que vous pouvez modifier via la `` méthode :

On dirait que vous voulez le pool de threads mis en cache avec un CallerRunsPolicy.

3voto

Jonathan Feinberg Points 24791

Par la Javadoc pour ThreadPoolExecutor :

S’il sont a plus de corePoolSize mais moins que maximumPoolSize threads s’exécutant, un nouveau thread sera créé uniquement si la file d’attente est pleine. En définissant corePoolSize et maximumPoolSize les mêmes, vous créez un pool de threads de taille fixe.

(Moi qui souligne).

réponse de gigue est ce que vous voulez, même si la mienne répond à votre autre question. :)

2voto

jitter Points 35805

C'est ce que vous voulez (au moins je pense que oui). Pour une explication de vérifier Jonathan Feinberg répondre

Executors.newFixedThreadPool(int n)

Crée un pool de threads qui réutilise un fixe le nombre de threads d'exploitation hors a partagé la surabondance de la file d'attente. À tout point, au plus nThreads threads être actif tâches de traitement. Si des tâches supplémentaires sont soumis lors de l' tous les threads sont actives, elles vont attendre dans la file d'attente jusqu'à ce qu'un thread est disponible. Si un thread se termine en raison d'un échec lors de l'exécution avant l'arrêt, un nouveau prendre sa place si nécessaire à l'exécution d' les tâches à venir. Les discussions dans le piscine existera jusqu'à ce qu'il soit explicitement de l'arrêt.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X