ScheduledThreadPool会产生OOM的源码剖析

ScheduledThreadPool阿里巴巴开发手册提到的问题

刚才看到阿里巴巴开发手册说
ScheduledThreadPool允许创建线程数量为Integer.MAX_VALUE,可能会创建大量线程,导致oom
如下:
在这里插入图片描述

ScheduledThreadPool源码剖析

但是我看到的DelayedWorkQueue内部基于动态数组。无限扩容。相当于无界队列了。

如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
那么,不应该是因为DelayedWorkQueue满导致oom吗?

线程池流程回顾

因为线程池的流程是:
在这里插入图片描述
所以阻塞队列满了之后才会创建临时线程去处理任务吧?
如果任务数量达到Integer.MAX_VALUE直接会oom吧?

因为先会向阻塞队列放元素。
所以不会创建大量线程的吧。

总结

所以我认为原因是:

  1. 由于延迟队列DelayedWorkQueue满导致OOM
  2. 如果堆空间足够创建Integer.MAX_VALUE级别的数组,才是手册提到的原因,会创建大量线程

两次实验

源码测试,反射拿到DelayedWorkQueue

@Test
    public void test() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        // 拿到内部类
        Class<?> delayedWorkQueueClass = Class.forName("java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue");

        System.out.println(delayedWorkQueueClass);

        // 拿到无参构造
        Constructor<?> constructor = delayedWorkQueueClass.getDeclaredConstructor();
        // 设置可访问状态
        constructor.setAccessible(true);
        // 实例对象
        Object delayedWorkQueue = constructor.newInstance();

        System.out.println(delayedWorkQueue);
        System.out.println(delayedWorkQueue.getClass());

        // 获取对应的queue字段
        Field field = delayedWorkQueueClass.getDeclaredField("queue");
        // 设置为可访问状态
        field.setAccessible(true);
        // 创建数组大小为Integer.MAX_VALUE - 5
        field.set(delayedWorkQueue, new RunnableScheduledFuture<?>[Integer.MAX_VALUE - 5]);
    }

在这里插入图片描述

并发测试

我试了循环200次使用该线程池执行任务,得到的结果是只有我初始容量5个线程在交替执行。
在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值