记一次线上OutOfMemoryError: unable to create new native thread

这次的内存溢出需要书接上回

记一次线上JVM内存占用率过高导致服务超时_行走的二进制的博客-CSDN博客进入后发现一个线程池对象占用了51%,而且是CompletableFuture的默认线程池,再深入就发现原来是在开启线程时往新线程中放入了一个大对象,由于商品又是访问量比较大的模块,就导致了多线程中大对象一直堆叠的情况。当时看到full gc次数是5,时间是2.13秒,感觉是full gc导致的服务超时(后面发现其实不是),于是使用jmap -dump命令把dump文件导出,并使用eclipse mat进行分析。优化方向就是不将大对象传入线程中,而是在只传对象id,在线程中查出需要的对象后再到主线程赋值。https://blog.csdn.net/hannnnn_/article/details/129721723?spm=1001.2014.3001.5501

上次堆内存过高的优化方案是:不将大对象传入线程中,而是在只传对象id,在线程中查出需要的对象后再到主线程赋值。在考虑到查询效率上,使用了多个线程分别查询额外属性,最后进行统一赋值。

 优化后上线一周,有一天服务突然报错:org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: unable to create new native thread

意思就是不能再创建新的线程,导致服务直接挂掉。

问题原因知道了是因为线程开的太多,但为什么能导致服务关闭呢?

既然是线程的问题,那就要先用top -H查看服务器当前线程数

 但服务已经挂掉了,在这里已经看不到开了多少线程

好在线上是两台服务,另一台虽然没挂,但线程数量肯定也很多,去另一台服务使用jstack pid > stack.log打印服务的线程日志

也可以把stack.log导入到这里进行分析Smart Java thread dump analyzer - thread dump analysis in secondsFree online thread dump analyzer to troubleshoot Java, android applications. Kotlin, Clojure, Scala, Jruby, Jython, all JVM language thread dumps are supported. hs_err_pid, core dump files are analyzed.https://fastthread.io/ft-index.jsp

 

 

发现全是WAITING状态的线程 ,且是LinkedBlockingQueue.take导致的,想到服务中自定义的线程池用的就是LinkedBlockingQueue。

看了一下线程池的文章发现线程使用完毕是需要将等待中的核心线程关闭的,而关闭有几种方法:

一般使用shutdown()方法和allowCoreThreadTimeOut(true)

如果为 false(默认值),则核心线程即使在空闲时也保持活动状态。
如果为 true,核心线程使用 keepAliveTime 定时等待工作。

看到这就发现为什么项目中有大量WAITING状态的线程,原来既没有手动关闭线程,也没有设置allowCoreThreadTimeOut为true,导致核心线程使用完毕后依旧在等待中

那么只需要使用executorService.allowCoreThreadTimeOut(true)就可以解决问题

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值