commons-pool2对象池分配回收策略
来源:互联网 发布:淘宝客服外包多少钱 编辑:程序博客网 时间:2024/05/17 04:33
commons-pool2对象池分配回收策略
前一段时间写了一个rpc的客户端,使用apache commons-pool2的对象池管理长连接。其中由于没有完全弄清楚各个参数的意义,即其中分配回收策略,所以出现了一些不太合理的现象。最近详细看了源码,这里整理一下。
一、对象的创建
1. 对象创建的时机
对象的创建有两个时机,一个是应用像对象池获取对象时;另一个是空闲对象回收后,判断需要保证minIdle数量的对象并重新创建对象。关于第二点在回收时再说,先梳理一下获取对象的过程。
2. 对象创建的条件
如上图所示,对象的创建如果满足下面的判断条件,则直接跳出,不会创建对象。判断条件中涉及到了两个值localMaxTotal 和newCreateCount ,localMaxTotal 就是对象池配置中的maxTotal(最大的对象个数);newCreateCount 表示当前对象池中对象的个数,每当创建一个对象这个数值加一,销毁一个对象这个数值减一。那么创建对象需要满足两个条件:
- 对象池中的对象没有达到上限maxTotal
- 对象池中的对象个数不能超过Integer类型的最大值
GenericObjectPool create方法中:if (localMaxTotal > -1 && newCreateCount > localMaxTotal || newCreateCount > Integer.MAX_VALUE) { createCount.decrementAndGet(); return null; }
3. 对象创建之后的工作
对象创建之后还有一个分配的过程。这个过程会把对象的状态修改为ALLOCATED,初始时是IDLE。同时会记录此对象本次被借出的时间、被借出的次数。如下代码所示:
if (state == PooledObjectState.IDLE) { state = PooledObjectState.ALLOCATED; lastBorrowTime = System.currentTimeMillis(); lastUseTime = lastBorrowTime; borrowedCount++; if (logAbandoned) { borrowedBy = new AbandonedObjectCreatedException(); } return true; }
分配完之后还有一个激活和验证的过程,分别调用factory中自定义的activateObject和validateObject方法。如果激活和验证过程失败,则会销毁这个创建好的对象。
二、对象的回收
1. 空闲对象回收线程的启动
public GenericObjectPool(PooledObjectFactory<T> factory, GenericObjectPoolConfig config) { super(config, ONAME_BASE, config.getJmxNamePrefix()); if (factory == null) { jmxUnregister(); // tidy up throw new IllegalArgumentException("factory may not be null"); } this.factory = factory; idleObjects = new LinkedBlockingDeque<PooledObject<T>>(config.getFairness()); setConfig(config); startEvictor(getTimeBetweenEvictionRunsMillis()); }
其实即使没有最后面的startEvictor(getTimeBetweenEvictionRunsMillis()),还是会启动evict线程,因为setConfig方法也会间接启动evict线程。
因为从config拷贝配置到对象池时,一定会拷贝timeBetweenEvictionRunsMillis参数,而对象池设置这个参数时就会启动evict线程
public final void setTimeBetweenEvictionRunsMillis( long timeBetweenEvictionRunsMillis) { this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; startEvictor(timeBetweenEvictionRunsMillis); }
2. 空闲对象回收线程的条件
一个空闲对象是否被回收,关键取决于EvictionPolicy的evict方法,而DefaultEvictionPolicy是它的唯一实现:
public boolean evict(EvictionConfig config, PooledObject<T> underTest, int idleCount) { if ((config.getIdleSoftEvictTime() < underTest.getIdleTimeMillis() && config.getMinIdle() < idleCount) || config.getIdleEvictTime() < underTest.getIdleTimeMillis()) { return true; } return false; }
可以看到,有两个参数影响了是否回收的结果,config.getIdleSoftEvictTime()和config.getIdleEvictTime()。他们对应连接池配置的softMinEvictableIdleTimeMillis和minEvictableIdleTimeMillis参数,只是在判断对象是否可回收前做了一些特殊的处理,如果设置了负数值,则会被转换为Long的最大值:
public EvictionConfig(long poolIdleEvictTime, long poolIdleSoftEvictTime, int minIdle) { if (poolIdleEvictTime > 0) { idleEvictTime = poolIdleEvictTime; } else { idleEvictTime = Long.MAX_VALUE; } if (poolIdleSoftEvictTime > 0) { idleSoftEvictTime = poolIdleSoftEvictTime; } else { idleSoftEvictTime = Long.MAX_VALUE; } this.minIdle = minIdle; }
softMinEvictableIdleTimeMillis和minEvictableIdleTimeMillis的两个判断条件只要满足其中一条即表示此对象可被回收。它们的区别在于空闲时间大于softMinEvictableIdleTimeMillis时,空闲对象的数量一定要大于配置的minIdle才可以;而minEvictableIdleTimeMillis只要大于空闲时间就成立。
所以,minEvictableIdleTimeMillis会暴力回收调空闲队列里的对象,不管空闲个数是否超过minIdle。而之后还会重新创建,导致对象被销毁又重建的现象发生。
3. 空闲对象回收线程其他的工作
evict线程不光做回收对象的工作。
1. 刚刚提到,如果回收后发现空闲队列中的对象个数已经小于minIdle,则会创建对象至minIdle个。
2. 如果不满足回收条件,则可以检查对象可用性,取决于testWhileIdle参数。检查的过程是先激活、再验证,如果失败则销毁对象。
4. 对象的销毁途径
- 空闲对象直接被evict线程回收
- borrow、return、evict过程中对象的激活、验证、挂起等操作出现异常
- return对象时对象池关闭或者maxIdle到了上限
- 应用主动调用invalidateObject或clear方法
- commons-pool2对象池分配回收策略
- commons pool2对象池入门
- commons pool2对象池的使用
- commons-pool2和commons-pool对象池使用
- 从commons pool2到池
- commons pool2
- Apache Commons Pool2连接池代码
- 利用Apache commons pool2构建池应用
- 利用Apache commons pool2构建池应用
- Apache common pool2 对象池
- 深入浅出commoms-pool2对象池
- Apache Commons Pool2-空闲对象的驱逐检测机制
- 9.《深入理解Java虚拟机》对象分配与回收策略
- jvm学习记录--06 垃圾回收对象内存分配策略
- commons.pool2 参数测试
- Apache Commons-pool2简记
- Apache Commons-pool2
- commons-pool2学习总结
- 通过TraceView定位卡顿问题
- SQL表连接查询(inner join、full join、left join、right join)
- MySQL 5 数据库基础语句总结
- Dubbo配置
- mysql insert锁机制
- commons-pool2对象池分配回收策略
- Struts2框架搭建
- 暴力搜索 寻找鞍点
- SQL语言学习心得
- Redis之对象
- hdu1242 Rescue(BFS +优先队列 or BFS )
- 5、linux常用不太记得住命令
- Retrofit2.0与RxJava2.0结合出现的问题解决
- 表格