ScheduledThreadPool阿里巴巴开发手册提到的问题
刚才看到阿里巴巴开发手册说
ScheduledThreadPool
允许创建线程数量为Integer.MAX_VALUE
,可能会创建大量线程,导致oom
。
如下:
ScheduledThreadPool源码剖析
但是我看到的DelayedWorkQueue
内部基于动态数组。无限扩容。相当于无界队列了。
如下:
那么,不应该是因为DelayedWorkQueue
满导致oom
吗?
线程池流程回顾
因为线程池的流程是:
所以阻塞队列满了之后才会创建临时线程去处理任务吧?
如果任务数量达到Integer.MAX_VALUE
直接会oom
吧?
因为先会向阻塞队列放元素。
所以不会创建大量线程的吧。
总结
所以我认为原因是:
- 由于延迟队列DelayedWorkQueue满导致OOM。
- 如果堆空间足够创建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个线程在交替执行。