日期:2014-05-20  浏览次数:20930 次

多线程下,机器性能太好,导致内存溢出??
本帖最后由 matrix1984 于 2013-09-16 10:42:18 编辑
写了一个处理数据的程序(读取文件数据,插入/更新数据库等),采用多线程(ThreadPoolExecutor),设置线程数:默认3个,最多5个(加主线程最多6个),在服务器A上起单独的jvm跑,没问题;
后来放在服务器B上(性能更好一些),发现在一个批量保存数据库的地方出现了OutOfMemory,感觉是不是线程数多了,就少一点,试到最后,发现只能用一个线程(即默认一个,最多2个),这样才能跑过去,这是因为机器性能好了,多线程在执行保存太快了导致的吗?机器内存啥的都是100G+,cpu也是很牛的,怎么会内存溢出?或者是启动的jvm给的内存不够?

请大神们个分析下,谢谢。

------解决方案--------------------
算你一条数据200个字段,每个字段8个字节,外加一个10000字节的文本,5000条也只有(200 * 8 + 10000) * 5000 = 58MB,3个线程撑死不到200MB内存。查看你的JVM启动内存吧
------解决方案--------------------
引用:
Quote: 引用:

理论上是可能的。你读取的文件速度太快,超过数据库操作了。

当然,代码设计上应该也是有漏洞的。可以考虑,如果队列里待处理的文件数很多,超过一个限额,就不再读取文件了。


我有一点忘记说了:改程序分两部分,1)读取文件数据,并先保存至数据库;2)读取数据库,进行处理(这里只涉及到数据库操作)。其实,多线程只发生在2)里头,所以跟文件读取无关。此外,2)当中是每读取5000数据放入一个线程进行处理,其间有批量保存数据(<=5000)的动作,OutOfMemory就是发生在这里。

应该是你查询数据库,得到的数据量超过你启动内存大小了。tomcat可以在catalina.sh中修改启动内存大小(默认好像是80M),其它容器的配置就不清楚了。
------解决方案--------------------
没设置jvm的内存吧
------解决方案--------------------
机器性能好导致内存溢出?开什么玩笑,啥关系没有.
你机器性能不好也不一定会溢出.
内存溢出就查一下jvm分配的内存是不是小了.另外跟踪一下单位时间插入数据库的数据量.
------解决方案--------------------
检查代码漏洞;调大JVM的-Xmx和Xms,让JVM有更多的可用内存空间。
------解决方案--------------------
读取的数据大小超过了jvm内存限制,跟机器什么关系。
------解决方案--------------------
内存不足有两种可能, jvm内存不足(此时可以尝试用楼上方法),本机内存不足(考虑是否是文件流操作有问题)
------解决方案--------------------
OutOfMemoryError 产生的原因是因为你在内存中加载了大量的数据,估计是你把文件全部读到了一个类似于 List 或者其他什么的数据结构中了,如果文件行数过大,最终只有这样一个结果!

你得读取一些数据操作完成后再去读取第二批数据,这样可以把内存占用控制在一个合理的范围之内,而且几乎不可能会出现 OutOfMemoryError 的错误!

这么大的内存对于这样的程序而言就是大材小用,应该从应用程序本身进行优化,而不是单纯地依赖于增加服务器的硬件配置。
------解决方案--------------------
问题的关键是:楼主的程序,没有控制内存的使用。
解决方案,
一般会设置JVM的最大内存占用值,但是,也会存在内存溢出的风险。
最好是能够优化程序代码,比如,重复使用缓冲区,数组等,尽量减少各种对象的创建操作。
还有,集合对象,使用完毕后,要调用clear方法等。