后果就是会造成内存溢出或者频繁的进行垃圾回收导致应用性能下降。
内存溢出
按照你目前的写法,在某一个时刻,同时有多个请求时,会创建大量的对象,请求时对象被引用无法回收,就会有内存溢出的风险。这就限制了程序并发能力。
频繁的垃圾回收
假设请求不是同一个时刻的。但随着时间的推移,jvm创建的对象会线性增加。
说到这里,我们先看下JVM的垃圾回收是怎样进行的?
大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC。
每次通讯会创建很多对象(放在Eden区域中),并且通讯结束后对象就不再使用了。因此当通讯比较频繁的时候,堆中的Eden中很快就会满了。就会触发垃圾回收(Minor GC)。而每次进行垃圾回收,jvm需要额外的线程进行处理,这个线程需要判断对象是否“已死”。部分垃圾回收器在回收过程中还会中断其他线程的工作,从而导致程序性能变差。
解决办法
明白了原理之后,解决方法就明晰了。就是要解决1、对象不要创建太多,最好有一个限制。2、对象不要太短命。
因此使用连接池是最好的选择连接池一般对外提供获得连接、归还连接的接口给客户端使用,并暴露最小空闲连接数、最大连接数等可配置参数,在内部则实现连接建立、连接心跳保持、连接管理、空闲连接回收、连接可用性检测等功能。
目前很多场景都用到了连接池的思想,例如数据库连接池、Redis连接池、http连接池。
使用连接池优势:每次连接使用完成后,不用关闭。归还连接。防止频繁的GC。
空闲时,连接池保存一定的连接,在使用时不必创建。
限制了最大连接数,防止了连接数过大导致内存溢出。
最后,建议你可以连接池的思想,结合单例模式、工厂方法等设计模式,重构你的通讯模块。
版权声明:本文为weixin_39626369原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。