这篇文章主要针对对线程池有一定了解的人,不了解原理的人建议先学习一下线程池的原理。
一般的,我们可能习惯这样创建线程池:
ExecutorService executorService = Executors.newCachedThreadPool();
ExecutorService executorService1 = Executors.newSingleThreadExecutor();
ExecutorService executorService2 = Executors.newFixedThreadPool(3);
ScheduledExecutorService executorService4 = Executors.newScheduledThreadPool(3);
看起来并没什么毛病。。。下面我们看看这几个方法实现的源码,你会发现其实都是通过ThreadPoolExecutor来创建的,这个ThreadPoolExecutor有多个构造函数,其中参数最多的为:

其他构造函数最终都是调了这个。然后我们先从newCachedThreadPool的实现看起,上源码:

你会发现这个最大线程数设置的是Integer.MAX_VALUE,相信看到这里大家应该意识到可能会发生什么问题了,没错,如果创建了大量的线程就有可能引发OOM。newScheduledThreadPool的分析过程和引发问题与此一致。
接下来我们再看看newSingleThreadExecutor的实现:

这里我们还看不出什么问题,我们再接着看new LinkedBlockingQueue(),

没错,你又看到了Integer.MAX_VALUE,这就是工作队列的大小,如果堆积了大量的任务,同样可能引发OOM。newFixedThreadPool的分析过程和
newSingleThreadExecutor一样,问题也一样,我就不再赘述。
既然有可能存在这样的坑,那么我们怎么避免呢?
我们可以这样创建:
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("francis-test").build();
ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 10, 5, TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
根据实际场景设置各参数,这样一来踩坑的几率会更小。
本文探讨了使用Java标准库创建线程池时可能遇到的问题,特别是由于不当配置导致的内存溢出风险。文章提供了具体的代码示例,并介绍了如何合理设置参数以规避这些潜在陷阱。
2142

被折叠的 条评论
为什么被折叠?



