续http://my.oschina.net/chengxiaoyuan/blog/607582 ,commons-pool2中有个驱逐机制Evictor定时任务,看其实怎么启动的 :java
在初始化对象池GenericObjectPool的时候对调用父类的startEvictor方法,父类初始化一个TimerTask的子类Evictor交由Timer定时执行,Evictor中的run方法最终仍是调用当前对象池的evict方法和ensureMinIdle方法,下面看具体的代码分析:ide
GenericObjectPool
测试
public GenericObjectPool(PooledObjectFactory<T> factory, GenericObjectPoolConfig config) { ...//省略 startEvictor(getTimeBetweenEvictionRunsMillis());//配置timeBetweenEvictionRunsMillis }
BaseGenericObjectPoolthis
final void startEvictor(long delay) { synchronized (evictionLock) { if (null != evictor) { EvictionTimer.cancel(evictor); evictor = null; evictionIterator = null; } //timeBetweenEvictionRunsMillis>0才会启动 if (delay > 0) { evictor = new Evictor(); EvictionTimer.schedule(evictor, delay, delay); } } }
BaseGenericObjectPool的内部类Evictor.net
/** * The idle object evictor {@link TimerTask}. * * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis */ class Evictor extends TimerTask { /** * Run pool maintenance. Evict objects qualifying for eviction and then * ensure that the minimum number of idle instances are available. * Since the Timer that invokes Evictors is shared for all Pools but * pools may exist in different class loaders, the Evictor ensures that * any actions taken are under the class loader of the factory * associated with the pool. */ @Override public void run() { ClassLoader savedClassLoader = Thread.currentThread().getContextClassLoader(); try { if (factoryClassLoader != null) { // Set the class loader for the factory ClassLoader cl = factoryClassLoader.get(); if (cl == null) { // The pool has been dereferenced and the class loader // GC'd. Cancel this timer so the pool can be GC'd as // well. cancel(); return; } Thread.currentThread().setContextClassLoader(cl); } // Evict from the pool try { evict();//具体的驱逐方法, 由具体子类实现 } catch(Exception e) { swallowException(e); } catch(OutOfMemoryError oome) { // Log problem but give evictor thread a chance to continue // in case error is recoverable oome.printStackTrace(System.err); } // Re-create idle instances. try { ensureMinIdle();//最后确保对象数等于最小空闲阀值 } catch (Exception e) { swallowException(e); } } finally { // Restore the previous CCL Thread.currentThread().setContextClassLoader(savedClassLoader); } } }
以GenericObjectPool为例看evict()和ensureMinIdle()code
public void evict() throws Exception { assertOpen(); if (idleObjects.size() > 0) {//若是空闲数大于0 PooledObject<T> underTest = null; EvictionPolicy<T> evictionPolicy = getEvictionPolicy();//evict的策略 synchronized (evictionLock) { EvictionConfig evictionConfig = new EvictionConfig( getMinEvictableIdleTimeMillis(), getSoftMinEvictableIdleTimeMillis(), getMinIdle());//驱逐配置,后面驱逐策略须要用到 boolean testWhileIdle = getTestWhileIdle();//空闲时检查开关 //getNumTests为每次检查对象数量 for (int i = 0, m = getNumTests(); i < m; i++) { if (evictionIterator == null || !evictionIterator.hasNext()) { evictionIterator = new EvictionIterator(idleObjects); } if (!evictionIterator.hasNext()) { // Pool exhausted, nothing to do here return; } try { underTest = evictionIterator.next(); } catch (NoSuchElementException nsee) { // Object was borrowed in another thread // Don't count this as an eviction test so reduce i; i--; evictionIterator = null; continue; } //修改状态 if (!underTest.startEvictionTest()) { // Object was borrowed in another thread // Don't count this as an eviction test so reduce i; i--; continue; } // User provided eviction policy could throw all sorts of // crazy exceptions. Protect against such an exception // killing the eviction thread. boolean evict; try { //根据策略进行判断是否须要驱逐,默认策略DefaultEvictionPolicy evict = evictionPolicy.evict(evictionConfig, underTest, idleObjects.size()); } catch (Throwable t) { // Slightly convoluted as SwallowedExceptionListener // uses Exception rather than Throwable PoolUtils.checkRethrow(t); swallowException(new Exception(t)); // Don't evict on error conditions evict = false; } if (evict) {//须要驱逐的对象直接销毁 destroy(underTest); destroyedByEvictorCount.incrementAndGet(); } else { if (testWhileIdle) {//若是空闲时检查 boolean active = false; try { factory.activateObject(underTest);//激活 active = true; } catch (Exception e) { destroy(underTest);//激活失败就销毁 destroyedByEvictorCount.incrementAndGet(); } if (active) { if (!factory.validateObject(underTest)) {//验证 destroy(underTest);//验证失败就销毁 destroyedByEvictorCount.incrementAndGet(); } else { try { factory.passivateObject(underTest);//验证成功就钝化 } catch (Exception e) { destroy(underTest); destroyedByEvictorCount.incrementAndGet(); } } } } //驱逐测试结束,修改状态 if (!underTest.endEvictionTest(idleObjects)) { // TODO - May need to add code here once additional // states are used } } } } } //移除废弃对象 AbandonedConfig ac = this.abandonedConfig; if (ac != null && ac.getRemoveAbandonedOnMaintenance()) { removeAbandoned(ac); } } private void ensureIdle(int idleCount, boolean always) throws Exception { if (idleCount < 1 || isClosed() || (!always && !idleObjects.hasTakeWaiters())) { return; } //若是空闲数小于最小阀值就一直建立对象 while (idleObjects.size() < idleCount) { PooledObject<T> p = create(); if (p == null) { // Can't create objects, no reason to think another call to // create will work. Give up. break; } if (getLifo()) { idleObjects.addFirst(p); } else { idleObjects.addLast(p); } } if (isClosed()) { // Pool closed while object was being added to idle objects. // Make sure the returned object is destroyed rather than left // in the idle object pool (which would effectively be a leak) clear(); } }
DefaultEvictionPolicy对象
public class DefaultEvictionPolicy<T> implements EvictionPolicy<T> { @Override public boolean evict(EvictionConfig config, PooledObject<T> underTest, int idleCount) { //1.若是对象空闲时间大于IdleSoftEvictTime而且空闲数量大于最小空闲阀值 //2.若是对象空闲时间大于IdleEvictTime //知足上面的一种状况就返回true if ((config.getIdleSoftEvictTime() < underTest.getIdleTimeMillis() && config.getMinIdle() < idleCount) || config.getIdleEvictTime() < underTest.getIdleTimeMillis()) { return true; } return false; } } //IdleEvictTime比IdleSoftEvictTime要严格一点,因此正常配置IdleEvictTime>IdleSoftEvictTime 这两个配置在BaseObjectPoolConfig中的体现: //IdleEvictTime对应配置为:minEvictableIdleTimeMillis //IdleSoftEvictTime对应配置为softMinEvictableIdleTimeMillis