爆炸的线程池😂

5,670 阅读3分钟

偶然看到一些文章,里面讲述到阿里巴巴JAVA开发手册(点击下载v1.4.0)关于线程池使用方面的说明。里面谈及到在项目中使用相关线程池,不允许使用Executors去创建。使用这种方式去实现线程池,有可能会导致一些问题。

原文图片:

于是小的不服输,想去一探究竟(办公电脑连续死机。。。真刺激)。

FixedThreadPool探究

本地写了一个关于FixedThreadPool的demo, 项目启动配置为:-Xms64m -Xmx192m -Xss1024K -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m

1.首先看看刚开始没有请求的情况下,内存,CPU以及线程数的情况:

2.然后开始请求(就不模仿外面一直循环调用了,直接在里面写死循环去模拟业务处理):

3.MetaSpace内存空间没多少太大的变化,主要是在Heap里面。CPU以及堆内存在请求的那一刻一度飙升,随着时间的进行,电脑散热器的声音越来越大😂。最后控制台出现了想要的东西:

4."OOM"-我想要的出现了。里面的RMI TCP Connection(idle)是我在堆dump的时候产生的问题,我们从文件中可以看到线程对应的状态为BLOCKED

5.同时我们查看当前项目中实例的大小情况:

里面最亮眼"仔"-Node。因为请求不断进入到程序里面,这个FixedThreadPool默认的大小为MAX_VALUE。则当线程数处理不过来的时候,则会将请求放在集合中,最后就会撑爆了当前的Heap。(额外多说一句:如果这种情况发生在中台服务里,那么你会很刺激😂)

CachedThreadPool探究

本地写了一个关于CachedThreadPool的demo, 项目启动配置为:-Xms64m -Xmx192m -Xss1024K -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m

服务刚开始的我们就不看了,跟上面的一样。我们直接看请求的情况(瞬间爆炸💥💥,然后电脑就重启了😑)明显的就是堆内存以及进程数。
然后控制台里面出现错误:
说明本地是无法创建一个操作系统级别的 native thread(原生线程),程序创建的线程数量已达到上限值。 然后我这边只能在终点之前查看堆dump(我要是等到终点再看,我电脑就又要重启了😑)。

我们可以查看到我们创建的线程多数处于TIMED_WAITING状态下,后面进来的都被阻塞住,原因由于当前线程池的队列特殊性,SynchronousQueue是一个比较特殊的阻塞队列实现类,它实际上并不会给元素维护一系列存储空间,它维护了一组线程,当尝试调用添加元素的方法时,必须要有另外一个线程尝试取出这些元素,否则就无法将元素"添加"进去。

总结

上面我就将两组情况都挑出一个线程池来说明了下,这里面其实主要是让小伙伴们知道,当我们程序中使用多线程最低要求是能够理解下线程池参数的说明,再根据业务访问量来大致确定各个参数的值。避免以上情况发生!!--- 可能我说的还不够全面(暂且没有撸里面集合的数据结构),希望有小伙伴底下评论补充~