现象:在项目中线程数量持续增长,且基本无法回收关闭,线程数量一直累积达到几万,影响CPU开销和性能,导致服务器卡死,连接上服务器后输入指令提示“无可分配内存”。
查找原因:
通过ps -eLf|grep '容器名'|wc -l命令找到项目的所占的线程数异常庞大,通过top -p pid H也发现该进程下大量占用资源的线程。进入容器内查看堆栈信息。
通过**jstack -l pid| grep 'java.lang.Thread.State'**发现项目的线程状态大多数都是WAITING(parking)状态,分析是线程一直处于等待状态一直在占用,造成GC无法执行,且新请求进来时造成线程占用累计。
打印当前JVM快照:**jstack 7 > /opt/test.dump**,查看快照定位原因:
分析原因:在我的业务中每次处理请求时都会创建一个线程池去多链路执行不同的流程,但是执行完毕后没有使用shutdown()关闭这个线程池对象,这样线程池仍会通过take方法去取等待队列中是否还有未完成的线程任务,等待队列为空时将会一直等待,这样就导致大量的线程hung在这里了(基本是只要方法被调一次,就会产生一个hung住的线程),所以有大量空线程一直占用,造成严重的线程泄漏。
总结:在自定义线程池且未交给spring容器管理时,使用完毕的线程池一定要执行shutDown()手动关闭线程池,这是编程上的疏忽。找到原因后感觉问题很简单,但是查找过程中还是碰壁不少,找过几次都没有找到最终原因。
参考:
来源地址:https://blog.csdn.net/qq_38783304/article/details/128936095