GenericObjectPoolConfig
GenericObjectPoolConfig
是在GenericObjectPool
构造的时候使用的,用来设置pool的maxTotal、maxIdle、minIdle等属性。
maxTotal比较好理解,表示pool中对象最多能有多少。主要是在create
函数中创建对象时进行判断
int localMaxTotal = getMaxTotal();
long newCreateCount = createCount.incrementAndGet();
if (localMaxTotal > -1 && newCreateCount > localMaxTotal ||
newCreateCount > Integer.MAX_VALUE) {
createCount.decrementAndGet();
return null;
}
maxIdle属性是指pool中最多能保留多少个空闲对象。这个属性主要是在returnObject
函数中使用的。在程序使用完相关的对象后,会调用returnObject函数将对象返回到pool中。但是如果当前maxIdleSave <= idleObjects.size()
,即当前pool中空闲对象的数量大于等于maxIdle时候,直接调用destroy
函数来销毁对象
int maxIdleSave = getMaxIdle();
if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) {
try {
destroy(p);
} catch (Exception e) {
swallowException(e);
}
}
minIdle属性是指pool中最少有多少个空闲对象。该属性主要是在evict
函数中调用。封装成EvictionConfig
对象后,调用EvictionPolicy中的evict方法来判断是否需要回收当前测试的对象。
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中设置的idleSoftEvictTime并且pool中空闲对象的数量大于minIdle,那么就会return true。然后就会回收销毁该对象。
其中EvictionConfig中的idleSoftEvictTime
和idleEvictTime
的默认值是在BaseObjectPoolConfig
中定义的。
/**
* The default value for the {@code minEvictableIdleTimeMillis}
* configuration attribute.
* @see GenericObjectPool#getMinEvictableIdleTimeMillis()
* @see GenericKeyedObjectPool#getMinEvictableIdleTimeMillis()
*/
public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS =
1000L * 60L * 30L;
/**
* The default value for the {@code softMinEvictableIdleTimeMillis}
* configuration attribute.
* @see GenericObjectPool#getSoftMinEvictableIdleTimeMillis()
* @see GenericKeyedObjectPool#getSoftMinEvictableIdleTimeMillis()
*/
public static final long DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = -1;
所以IdleSoftEvictTime
和IdleEvictTime
的默认值分别是-1和半小时
evict函数是有一个定时任务定时去调用的。所以pool中一般会维持minIdle个闲置对象。所以如果当前pool中闲置对象的数量小于minIdle,pool并不会创建新的对象。minIdle只是用来回收对象的时候进行判断。
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 {
...
// 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.
...
} finally {
// Restore the previous CCL
Thread.currentThread().setContextClassLoader(savedClassLoader);
}
}
}
该定时器是在GenericObjectPool
的构造函数中调用的,调用间隔是由timeBetweenEvictionRunsMillis
参数控制的。timeBetweenEvictionRunsMillis
的默认值是-1L。这个时候定时器任务是不启用的,所以不会去调用evict来回收对象。
/**
* <p>Starts the evictor with the given delay. If there is an evictor
* running when this method is called, it is stopped and replaced with a
* new evictor with the specified delay.</p>
*
* <p>This method needs to be final, since it is called from a constructor.
* See POOL-195.</p>
*
* @param delay time in milliseconds before start and between eviction runs
*/
final void startEvictor(long delay) {
synchronized (evictionLock) {
if (null != evictor) {
EvictionTimer.cancel(evictor);
evictor = null;
evictionIterator = null;
}
if (delay > 0) {
evictor = new Evictor();
EvictionTimer.schedule(evictor, delay, delay);
}
}
}