续http://my.oschina.net/chengxiaoyuan/blog/607582 ,commons-pool2中有个驱逐机制Evictor定时任务,看其实怎么启动的 :
在初始化对象池GenericObjectPool的时候对调用父类的startEvictor方法,父类初始化一个TimerTask的子类Evictor交由Timer定时执行,Evictor中的run方法最终还是调用当前对象池的evict方法和ensureMinIdle方法,下面看具体的代码分析:
GenericObjectPool
public GenericObjectPool(PooledObjectFactory<T> factory,
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
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