Core pool size vs maximum pool size in ThreadPoolExecutor

后端 未结 10 1075
滥情空心
滥情空心 2020-11-29 16:08

What exactly is the difference between core pool size and maximum pool size when we talk in terms of ThreadPoolExecutor?
C

10条回答
  •  醉酒成梦
    2020-11-29 16:56

    Understanding the internal behavior of the ThreadPoolExecutor when a new task is submitted helped me understand how corePoolSize and maximumPoolSize differ.

    Let:

    • N be the number of threads in the pool, getPoolSize(). Active threads + idle threads.
    • T be the amount of tasks submitted to the executor/pool.
    • C be the core pool size, getCorePoolSize(). How many threads can at most be created per pool for the incoming tasks before new tasks go to the queue.
    • M be the maximum pool size, getMaximumPoolSize(). Maximum amount of threads the pool can allocate.

    Behaviors of the ThreadPoolExecutor in Java when a new task is submitted:

    • For N <= C, the idle threads are not assigned the new incoming task, instead a new thread is created.
    • For N > C and if there are idle threads then new task is assigned there.
    • For N > C and if there are NO idle threads, new tasks are put into the queue. NO NEW THREAD CREATED HERE.
    • When queue is full, we create new threads up to M. If M is reached, we reject the tasks. What's important to not here is that we do not create new threads until the queue is full!

    Sources:

    • docs.oracle.com
    • excellent article on the subject.

    Examples

    Example with corePoolSize = 0 and maximumPoolSize = 10 with a queue capacity of 50.

    This will result in one single active thread in the pool until the queue has 50 items in it.

    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.
    
    

    Example with corePoolSize = 10 and maximumPoolSize = 10 with a queue capacity of 50.

    This will result in 10 active threads in the pool. When the queue has 50 items in it, tasks will be rejected.

    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`. 
    
    

提交回复
热议问题