探究Executors创建的线程池(如newFixedThreadPool)其核心线程数等参数的可调整性

java中提供Executors类来创建一些固定模板参数的线程池,如下图(newWorkStealingPool除外,这个是创建ForkJoinPool的,这里忽略):
在这里插入图片描述
newFixedThreadPool方法创建线程池为例,newFixedThreadPool是创建一个指定线程数的线程池,所以就好奇创建完成之后,是否可以改变他的线程池配置,比如调大核心线程数。于是就查看了一下源码,此方法中,核心线程数和最大线程数都是形参中传入的大小,keepAlive时间为0,返回的对象是ThreadPoolExecutor类,ThreadPoolExecutor提供了一系列的修改线程池配置的方法。也就是说通过这种方式创建线程池对象的核心线程数等参数动态调整是可行的。
在这里插入图片描述
在下面的代码中,创建了一个线程数量为2的固定线程池对象,然后改变其核心线程池大小,添加9个任务,最后输出,发现核心线程数参数确实被改变了。

    public void testFixed() {
        ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
        executorService.setCorePoolSize(3);
        executorService.setMaximumPoolSize(5);
        executorService.execute(() -> ThreadUtil.sleep(100_000));
        executorService.execute(() -> ThreadUtil.sleep(100_000));
        executorService.execute(() -> ThreadUtil.sleep(100_000));
        executorService.execute(() -> ThreadUtil.sleep(100_000));
        executorService.execute(() -> ThreadUtil.sleep(100_000));
        executorService.execute(() -> ThreadUtil.sleep(100_000));
        executorService.execute(() -> ThreadUtil.sleep(100_000));
        executorService.execute(() -> ThreadUtil.sleep(100_000));
        executorService.execute(() -> ThreadUtil.sleep(100_000));
        ThreadUtil.sleep(2_000);
        System.out.println(executorService.getCorePoolSize()); // 3
        System.out.println(executorService.getMaximumPoolSize()); // 5
        System.out.println(executorService.getActiveCount()); // 3 活动的线程大小为3是因为队列还没有满,所以不会去新建新的线程(<=最大线程数)
        System.out.println(executorService.getQueue().size()); // 6
    }

newCachedThreadPool返回值实际上也是一个ThreadPoolExecutor对象,所以也可以在创建之后动态调整,但其设置的最大线程数量是Integer的最大值。需要注意的一点是,newCachedThreadPool创建的线程池使用的是SynchronousQueue队列,这种一种同步队列,不存放元素,插入和移除元素是配对的。因此会导致一个问题,也就是当我们将最大线程数调小,当任务量超过了这个最大线程数的时候,就会发现异常,提示说任务被拒绝,因为每个任务都需要一个线程

ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newCachedThreadPool();
        executorService.setCorePoolSize(20);
        executorService.setMaximumPoolSize(50);
        executorService.execute(() -> ThreadUtil.sleep(100_000));
        executorService.execute(() -> ThreadUtil.sleep(100_000));
        executorService.execute(() -> ThreadUtil.sleep(100_000));
        executorService.execute(() -> ThreadUtil.sleep(100_000));
        executorService.execute(() -> ThreadUtil.sleep(100_000));
        executorService.execute(() -> ThreadUtil.sleep(100_000));
        executorService.execute(() -> ThreadUtil.sleep(100_000));
        executorService.execute(() -> ThreadUtil.sleep(100_000));
        executorService.execute(() -> ThreadUtil.sleep(100_000));
        ThreadUtil.sleep(2_000);
        System.out.println(executorService.getCorePoolSize()); // 20
        System.out.println(executorService.getMaximumPoolSize()); // 50
        System.out.println(executorService.getActiveCount()); // 9
        System.out.println(executorService.getQueue().size()); // 0

将最大线程调整到6,核心调整为5,运行程序,报错
在这里插入图片描述
newScheduledThreadPool方法返回的是一个ScheduledThreadPoolExecutor对象ScheduledThreadPoolExecutor类是ThreadPoolExecutor子类,所以也允许调整。
newSingleThreadExecutor方法返回的是一个包装类,并没有提供设置线程池参数的方法。
在这里插入图片描述
在这里插入图片描述

无法强转成ThreadPoolExecutor类型,强转的话,会发生转换异常

(ThreadPoolExecutor) Executors.newSingleThreadExecutor();
在这里插入图片描述

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值