ThreadPoolExecutor中活跃的线程数超过corePoolSize后新来的请求会进入阻塞队列

关于该类的文档 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html

描述中有以下内容

Core and maximum pool sizes

............. When a new task is submitted in method execute(java.lang.Runnable), and fewer than corePoolSize threads are running, a new thread is created to handle the request, even if other worker threads are idle. If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full.

当方法execute(java.lang.Runnable)中提交新任务并且运行的线程少于corePoolSize时,即使其他工作线程处于空闲状态,也会创建一个新线程来处理该请求。如果运行的线程数于介corePoolSizemaxi与mumPoolSize之间,则只有在队列已满时才会创建新线程。

Queuing

Any BlockingQueue may be used to transfer and hold submitted tasks. The use of this queue interacts with pool sizing:

  • If fewer than corePoolSize threads are running, the Executor always prefers adding a new thread rather than queuing.
  • If corePoolSize or more threads are running, the Executor always prefers queuing a request rather than adding a new thread.
  • If a request cannot be queued, a new thread is created unless this would exceed maximumPoolSize, in which case, the task will be rejected.

加粗部分意思: 如果线程池里的线程数大于corePoolSize,Executor会将新来的请求放进队列而不是增加一个新线程。

 

下面编写代码来证明:

public class ThreadPoolTest {

    public static void main(String[] args) {

       try {
           createThreadDemo();
       } catch (RejectedExecutionException e) {
           e.printStackTrace();
           System.exit(-1);
       }

    }

    private static void createThreadDemo() throws RejectedExecutionException {

        // 等待队列
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(6);

        // 创建线程池, 核心线程数为5, 最大线程数为10
        ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 10, 600, TimeUnit.SECONDS, workQueue);

        for (int i = 1; i < Integer.MAX_VALUE; i++) {

            pool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName());
                    try {
                        Thread.sleep(300000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });

            System.out.println("创建第" + i + "个线程后, 线程池情况:" + pool.toString());
        }
    }

}

输出:

pool-1-thread-1

创建第1个线程后, 线程池情况:java.util.concurrent.ThreadPoolExecutor@78457235[Running, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]

pool-1-thread-2

创建第2个线程后, 线程池情况:java.util.concurrent.ThreadPoolExecutor@78457235[Running, pool size = 2, active threads = 2, queued tasks = 0, completed tasks = 0]

pool-1-thread-3

创建第3个线程后, 线程池情况:java.util.concurrent.ThreadPoolExecutor@78457235[Running, pool size = 3, active threads = 3, queued tasks = 0, completed tasks = 0]

pool-1-thread-4

创建第4个线程后, 线程池情况:java.util.concurrent.ThreadPoolExecutor@78457235[Running, pool size = 4, active threads = 4, queued tasks = 0, completed tasks = 0]

pool-1-thread-5

创建第5个线程后, 线程池情况:java.util.concurrent.ThreadPoolExecutor@78457235[Running, pool size = 5, active threads = 5, queued tasks = 0, completed tasks = 0]

创建第6个线程后, 线程池情况:java.util.concurrent.ThreadPoolExecutor@78457235[Running, pool size = 5, active threads = 5, queued tasks = 1, completed tasks = 0]

创建第7个线程后, 线程池情况:java.util.concurrent.ThreadPoolExecutor@78457235[Running, pool size = 5, active threads = 5, queued tasks = 2, completed tasks = 0]

创建第8个线程后, 线程池情况:java.util.concurrent.ThreadPoolExecutor@78457235[Running, pool size = 5, active threads = 5, queued tasks = 3, completed tasks = 0]

创建第9个线程后, 线程池情况:java.util.concurrent.ThreadPoolExecutor@78457235[Running, pool size = 5, active threads = 5, queued tasks = 4, completed tasks = 0]

创建第10个线程后, 线程池情况:java.util.concurrent.ThreadPoolExecutor@78457235[Running, pool size = 5, active threads = 5, queued tasks = 5, completed tasks = 0]

创建第11个线程后, 线程池情况:java.util.concurrent.ThreadPoolExecutor@78457235[Running, pool size = 5, active threads = 5, queued tasks = 6, completed tasks = 0]

pool-1-thread-6

创建第12个线程后, 线程池情况:java.util.concurrent.ThreadPoolExecutor@78457235[Running, pool size = 6, active threads = 6, queued tasks = 6, completed tasks = 0]

pool-1-thread-7

创建第13个线程后, 线程池情况:java.util.concurrent.ThreadPoolExecutor@78457235[Running, pool size = 7, active threads = 7, queued tasks = 6, completed tasks = 0]

pool-1-thread-8

创建第14个线程后, 线程池情况:java.util.concurrent.ThreadPoolExecutor@78457235[Running, pool size = 8, active threads = 8, queued tasks = 6, completed tasks = 0]

pool-1-thread-9

创建第15个线程后, 线程池情况:java.util.concurrent.ThreadPoolExecutor@78457235[Running, pool size = 9, active threads = 9, queued tasks = 6, completed tasks = 0]

pool-1-thread-10

创建第16个线程后, 线程池情况:java.util.concurrent.ThreadPoolExecutor@78457235[Running, pool size = 10, active threads = 10, queued tasks = 6, completed tasks = 0]

Disconnected from the target VM, address: '127.0.0.1:52079', transport: 'socket'

java.util.concurrent.RejectedExecutionException: Task utils.ThreadPoolTest$1@563da1dc rejected from java.util.concurrent.ThreadPoolExecutor@78457235[Running, pool size = 10, active threads = 10, queued tasks = 6, completed tasks = 0]

at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2048)

at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:821)

at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1372)

at utils.ThreadPoolTest.createThreadDemo(ThreadPoolTest.java:32)

at utils.ThreadPoolTest.main(ThreadPoolTest.java:15)

我们创建了一个corePoolSize为5、maximumPoolSize为10的线程池。 由结果得知, 当线程池内活跃的线程数大于5时,再来新的创建请求会直接进入队列(队列数往上增),直接到达队列的界限(这里是6)后, 再来新的请求时pool size会一直增大直到达到maximumPoolSize为止。 

结论: 线程池内活跃的线程数大于corePoolSize时, 新来的任务会先进队列, 如果队列满时会继续新建线程直到池内线程数达到maximumPoolSize为止。 这时如果再请求新的任务, 会执行设定的策略, 默认是直接拒绝创建。

 

 

 

 

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值