YU000HONG

持续学习,努力向前~

commons-pool 源码分析:池对象的生命周期

2019-03-27     标签:  对象池  连接池  线程池

PooledObjectState

PooledObjectState是一个枚举类,表示对象在对象池的当前状态,有如下状态:

  • IDLE:对象处于空闲状态
  • ALLOCATED:表示对象已经被借出,正在使用
  • EVICTION:对象正在进行驱逐检测
  • EVICTION_RETURN_TO_HEAD:在对象处于驱逐检测过程中时被强行allocate()
  • INVALID:经过驱逐检测发现,这个空闲对象需要被驱逐,将被置为INVALID
  • ABANDONED:被丢弃状态
  • RETURNING:将对象归还到对象池中时,对象的一个临时状态
  • VALIDATION:暂时未使用
  • VALIDATION_PREALLOCATED:暂时未使用
  • VALIDATION_RETURN_TO_HEAD:暂时未使用

DefaultPooledObject

所有的池对象最终都会被包装为一个PooledObject对象,PooledObject是一个接口,默认实现类为DefaultPooledObjectDefaultPooledObject这个包装类除了维护对象状态外,还提供了一些辅助信息(如对象创建时间、Idle时间、Active时间、上次借出时间、上次归还时间等),便于我们对对象生命周期的管理。

对象生命周期相关的方法有:

  • startEvictionTest()
  • endEvictionTest()
  • allocate()
  • deallocate()
  • invalidate()
  • markAbandoned()
  • markReturning()
  • use()

startEvictionTest()

这个方法在Evictor线程执行evict()方法时被调用,开始执行驱逐检测,对象将被置为EVICTION状态。

endEvictionTest()

这个方法在Evictor线程执行evict()方法时被调用,表示完成驱逐检测。如果对象满足驱逐条件时,将被置为INVALID状态然后被销毁;如果对象不满足驱逐条件,那么将会被重新置为IDLE状态。

allocate()

在借出对象(调用borrowObject()方法)时,会调用对象的allocate方法;如果对象当前处于IDLE状态,表明对象目前处于空闲状态可以借出,此时对象将被置为ALLOCATED状态;如果对象处于EVICTION状态,表明对象正处于驱逐检测过程中,对象将被置为EVICTION_RETURN_TO_HEAD,然后在完成驱逐检测时该对象将被移到空闲队列的最前端(为什么要移到最前端呢?)。

deallocate()

在归还对象(调用returnObject()方法)时,会调用对象的deallocate方法,对象将被重新置为IDLE状态。

invalidate()

当对象因为各种原因需要被销毁时,会调用该方法,将对象状态置为INVALID,同时会从空闲对象列表和全部对象列表中移除对应的对象。

那么,什么时候对象需要销毁呢?

  • 调用PooledObjectFactory.activateObject()异常时
  • 调用PooledObjectFactory.passivateObject()异常时
  • 调用PooledObjectFactory.validateObject()异常或失败时
  • 主动调用ObjectPool.invalidateObject()方法
  • 主动调用ObjectPool.clear()方法
  • evict()的过程中,对象需要被驱逐的时候

等等,不是应该还有丢弃操作(Abandon)也会销毁对象么?对,丢弃操作也会销毁对象,但是丢弃操作没有直接进行销毁,而是主动调用了ObjectPool.invalidateObject()方法。

markAbandoned()

当对象池整体状态满足进行丢弃操作的条件时,对象池会对所有对象进行一次丢弃检测。如果对象需要被丢弃,那么将调用该方法将对象状态置为ABANDONED

markReturning()

当归还对象时,将会调用该方法将对象的状态置为RETURNING,然后在一系列处理(factory.validateObject(),factory.passivateObject())之后对象的最终状态将被置为IDLE

那这里为什么会有一个中间状态呢?因为这里存在并发问题,在归还过程的同时有可能对象正在被丢弃。如果丢弃操作先占用,那么对象将被置为ABANDONED,然后INVALID,直至销毁;如果归还操作先占用,那么对象将被置为RETURNING,然后IDLE,最终变成空闲对象。

use()

这个方法用于设置对象的lastUseTime,避免对象被丢弃。

状态转移图

这里需要说明的是:

任何状态都有可能因为某些原因而进行INVALID状态