ThreadPoolExecutor解析

ThreadPoolExecutor解析

最近在研究多线程开发,在构建线程池的时候,常用ThreadPoolExecutor构建,但对于其构造方法中的入参不是很清楚,所以记录一下

ThreadPoolExecutor线程池构建

先上构造方法

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

这是一个比较基础的构建方法,下面对参数进行剖析

  1. corePoolSize

    线程池核心线程数,当前线程池中线程数少于corePoolSize的时候,会新建一个线程,放入线程池,并开始执行线程

  2. maximumPoolSize

    线程池最大线程数,线程池中能创建的最大线程数

  3. keepAliveTime

    线程池中空闲线程的最大保留时间,过期销毁

  4. unit

    最大保留时间单位

  5. workQueue

    线程阻塞队列,当新请求进入时,若当前线程池中线程数大于corePoolSize时,会将线程放入阻塞队列中,等待执行

    线程阻塞有多种方式,这里先使用LinkedBlockingDeque进行阻塞,可以设置阻塞队列能放入的线程数

    当超过阻塞队列数时,并且当前线程池存活线程数少于maximumPoolSize时,超过的线程会放入线程池,开始执行,当线程池存活线程数大于maximumPoolSize时,会抛异常RejectedExecutionException

    线程池存活线程数可以通过 threadPoolExecutor.getActiveCount() 获取

上代码

public class TestThread {
    private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 11, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(8));

    public static void main(String[] args) {
        for (int i = 0; i < 20; i++) {
            int finalI = i;
            Runnable runnable = () -> {
                System.out.println("线程" + finalI + "加入");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程" + finalI + "结束");
            };
            threadPoolExecutor.execute(runnable);
            System.out.println("线程池队列:" + threadPoolExecutor.getQueue().size());
            System.out.println("活动线程:" + threadPoolExecutor.getActiveCount());
        }
        threadPoolExecutor.shutdown();
    }
}

代码运行结果

线程池队列:0
线程0加入
活动线程:1
线程池队列:0
活动线程:2
线程1加入
线程池队列:0
活动线程:3
线程2加入
线程池队列:0
活动线程:4
线程3加入
线程池队列:0
活动线程:5
线程4加入
线程池队列:1
活动线程:5
线程池队列:2
活动线程:5
线程池队列:3
活动线程:5
线程池队列:4
活动线程:5
线程池队列:5
活动线程:5
线程池队列:6
活动线程:5
线程池队列:7
活动线程:5
线程池队列:8
活动线程:5
线程池队列:8
活动线程:6
线程13加入
线程池队列:8
活动线程:7
线程14加入
线程池队列:8
活动线程:8
线程15加入
线程池队列:8
活动线程:9
线程16加入
线程池队列:8
活动线程:10
线程17加入
线程池队列:8
活动线程:11
线程18加入
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.guozhaoning.shop.TestThred$$Lambda$1/485815673@5e8c92f4 rejected from java.util.concurrent.ThreadPoolExecutor@61e4705b[Running, pool size = 11, active threads = 11, queued tasks = 8, completed tasks = 0]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
	at com.guozhaoning.shop.TestThred.main(TestThred.java:32)
线程4结束
线程13结束
线程18结束
线程7加入
线程2结束
线程8加入
线程1结束
线程9加入
线程3结束
线程10加入
线程16结束
线程17结束
线程0结束
线程14结束
线程15结束
线程12加入
线程11加入
线程6加入
线程5加入
线程10结束
线程5结束
线程9结束
线程6结束
线程8结束
线程11结束
线程12结束
线程7结束

可以看出代码会抛出异常,这是因为需要创建的线程已经超过线程池最大数量,线程池会拒绝

计算能创建的实际最大线程数 (线程持续运行条件下)

为什么会提出这个问题?

因为在运行代码的时候,发现我设置的最大线程数是11,但是时间上是创建并且运行成功了19个线程,这个数字是怎么来的,有必要记录一下

首先能够直接创建的线程是是corePoolSize = 5,第6个至第13个线程共8个线程会放入阻塞队列,资源释放后会执行,那么第14个线程怎么处理?这个时候就需要找存活线程数量与线程池最大线程数,当前存活线程是5 ,5是之前放入线程池的5个线程,而线程池中最大线程是11,那么从第十四个线程开始,将放入线程池,不再放入阻塞队列,还能再放6个,所以一共创建的线程是 5 + 8 + 6 = 19

也就是 corePoolSize + workQueueNum + (maximumPoolSize - corePoolSize)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值