续 ,commons-pool2中有个驱逐机制Evictor定时任务,看其实怎么启动的 :
在初始化对象池GenericObjectPool的时候对调用父类的startEvictor方法,父类初始化一个TimerTask的子类Evictor交由Timer定时执行,Evictor中的run方法最终还是调用当前对象池的evict方法和ensureMinIdle方法,下面看具体的代码分析:
GenericObjectPool
public GenericObjectPool(PooledObjectFactoryfactory, GenericObjectPoolConfig config) { ...//省略 startEvictor(getTimeBetweenEvictionRunsMillis());//配置timeBetweenEvictionRunsMillis }
BaseGenericObjectPool
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
/** * 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()
public void evict() throws Exception { assertOpen(); if (idleObjects.size() > 0) {//如果空闲数大于0 PooledObjectunderTest = null; EvictionPolicy 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 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 DefaultEvictionPolicyimplements EvictionPolicy { @Override public boolean evict(EvictionConfig config, PooledObject 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