Quelle est la différence exacte entre taille du pool de base y taille maximale de la piscine quand on parle en termes de ThreadPoolExecutor
?
Peut-on l'expliquer à l'aide d'un exemple ?
Réponses
Trop de publicités?Comprendre le comportement interne de la ThreadPoolExecutor
quand une nouvelle tâche est soumise m'a aidé à comprendre comment corePoolSize
y maximumPoolSize
différents.
Laissez :
-
N
est le nombre de threads dans le pool,getPoolSize()
. Threads actifs + threads inactifs. -
T
être la quantité de tâches soumises à l'exécuteur/pool. -
C
est la taille du pool de base,getCorePoolSize()
. Combien de threads peuvent être créés au maximum par pool pour les tâches entrantes ? avant que les nouvelles tâches ne soient placées dans la file d'attente . -
M
soit la taille maximale du pool,getMaximumPoolSize()
. Nombre maximum de threads que le pool peut allouer.
Comportements de la ThreadPoolExecutor
en Java lorsqu'une nouvelle tâche est soumise :
- Pour
N <= C
les threads inactifs ne sont pas affectés à la nouvelle tâche entrante, mais un nouveau thread est créé. - Pour
N > C
et s'il y a des fils libres, une nouvelle tâche y est assignée. - Pour
N > C
et s'il n'y a PAS de threads inactifs, de nouvelles tâches sont placées dans la file d'attente. AUCUN NOUVEAU FIL DE DISCUSSION N'A ÉTÉ CRÉÉ ICI. -
Lorsque la file d'attente est pleine nous créons de nouveaux fils jusqu'à
M
. SiM
est atteint, nous rejetons les tâches. Ce qu'il est important de noter ici, c'est que nous ne créons pas de nouveaux threads tant que la file d'attente n'est pas pleine !
Sources :
Exemples
Exemple avec corePoolSize = 0
y maximumPoolSize = 10
avec une capacité de file d'attente de 50
.
Il n'y aura donc qu'un seul thread actif dans le pool jusqu'à ce que la file d'attente contienne 50 éléments.
executor.execute(task #1):
before task #1 submitted to executor: java.util.concurrent.ThreadPoolExecutor@c52dafe[Running, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
after task #1 submitted to executor: java.util.concurrent.ThreadPoolExecutor@c52dafe[Running, pool size = 1, active threads = 1, queued tasks = 1, completed tasks = 0]
[task #1 immediately queued and kicked in b/c the very first thread is created when `workerCountOf(recheck) == 0`]
execute(task #2):
before task #2 submitted to executor: java.util.concurrent.ThreadPoolExecutor@c52dafe[Running, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]
after task #2 submitted to executor: java.util.concurrent.ThreadPoolExecutor@c52dafe[Running, pool size = 1, active threads = 1, queued tasks = 1, completed tasks = 0]
[task #2 not starting before #1 is done]
... executed a few tasks...
execute(task #19)
before task #19 submitted to executor: java.util.concurrent.ThreadPoolExecutor@735afe38[Running, pool size = 1, active threads = 1, queued tasks = 17, completed tasks = 0]
after task #19 submitted to executor: java.util.concurrent.ThreadPoolExecutor@735afe38[Running, pool size = 1, active threads = 1, queued tasks = 18, completed tasks = 0]
...
execute(task #51)
before task submitted to executor: java.util.concurrent.ThreadPoolExecutor@735afe38[Running, pool size = 1, active threads = 1, queued tasks = 50, completed tasks = 0]
after task submitted to executor: java.util.concurrent.ThreadPoolExecutor@735afe38[Running, pool size = 2, active threads = 2, queued tasks = 50, completed tasks = 0]
Queue is full.
A new thread was created as the queue was full.
Exemple avec corePoolSize = 10
y maximumPoolSize = 10
avec une capacité de file d'attente de 50
.
Il y aura ainsi 10 threads actifs dans le pool. Lorsque la file d'attente contient 50 éléments, les tâches seront rejetées.
execute(task #1)
before task #1 submitted to executor: java.util.concurrent.ThreadPoolExecutor@32d9e072[Running, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
after task #1 submitted to executor: java.util.concurrent.ThreadPoolExecutor@32d9e072[Running, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]
execute(task #2)
before task #2 submitted to executor: java.util.concurrent.ThreadPoolExecutor@32d9e072[Running, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]
after task #2 submitted to executor: java.util.concurrent.ThreadPoolExecutor@32d9e072[Running, pool size = 2, active threads = 2, queued tasks = 0, completed tasks = 0]
execute(task #3)
before task #3 submitted to executor: java.util.concurrent.ThreadPoolExecutor@32d9e072[Running, pool size = 2, active threads = 2, queued tasks = 0, completed tasks = 0]
after task #3 submitted to executor: java.util.concurrent.ThreadPoolExecutor@32d9e072[Running, pool size = 3, active threads = 3, queued tasks = 0, completed tasks = 0]
... executed a few tasks...
execute(task #11)
before task #11 submitted to executor: java.util.concurrent.ThreadPoolExecutor@32d9e072[Running, pool size = 10, active threads = 10, queued tasks = 0, completed tasks = 0]
after task #11 submitted to executor: java.util.concurrent.ThreadPoolExecutor@32d9e072[Running, pool size = 10, active threads = 10, queued tasks = 1, completed tasks = 0]
... executed a few tasks...
execute(task #51)
before task #51 submitted to executor: java.util.concurrent.ThreadPoolExecutor@32d9e072[Running, pool size = 10, active threads = 10, queued tasks = 50, completed tasks = 0]
Task was rejected as we have reached `maximumPoolSize`.
Selon la documentation :
Toute BlockingQueue peut être utilisée pour transférer et retenir les tâches soumises. L'utilisation de cette file d'attente interagit avec le dimensionnement du pool : si moins de taille du pool de base sont en cours d'exécution, l'exécuteur préfère toujours ajouter un nouveau nouveau thread plutôt que de mettre en file d'attente. Si des threads de la taille d'un core pool ou plus sont s'exécutent, l'exécuteur préfère toujours mettre une requête en file d'attente plutôt que plutôt que d'ajouter un nouveau thread. Si une requête ne peut être mise en file d'attente, un nouveau thread est créé, à moins que cela ne dépasse la taille maximale du pool, auquel cas la tâche ne sera pas mise en attente. tâche sera rejetée.
Cela signifie que la taille du core pool est le seuil au-delà duquel le service d'exécution préfère mettre la tâche en file d'attente plutôt que de lancer un nouveau thread. Si, lors de la réception d'une tâche, le nombre de threads est inférieur à la taille du core pool, la création d'un nouveau thread est effectuée, augmentant ainsi le nombre de threads actifs.
- Réponses précédentes
- Plus de réponses