commons-pool2中GenericObjectPoolConfig的maxTotal、maxIdle、minIdle属性理解

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中的idleSoftEvictTimeidleEvictTime的默认值是在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;

所以IdleSoftEvictTimeIdleEvictTime的默认值分别是-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);
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章