GenericObjectPool是用来作为链接池实现的,用来和PooledObjectFactory组合使用可以对外提供一个健壮的链接池。
//最大空闲链接
private volatile int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE;
//最小空闲链接
private volatile int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE;
//对象生成工厂
private final PooledObjectFactory factory;
//对象总数 < 配置的最大链接数
private final Map, PooledObject> allObjects =
new ConcurrentHashMap<>();
//已创建对象总数
private final AtomicLong createCount = new AtomicLong(0);
//调用创建方法的总线程数
private long makeObjectCount = 0;
//makeObjectCount 增长时的锁
private final Object makeObjectCountLock = new Object();
//空闲对象队列
private final LinkedBlockingDeque> idleObjects;
1. 基础构造函数
public GenericObjectPool(final PooledObjectFactory factory,
final GenericObjectPoolConfig config) {
super(config, ONAME_BASE, config.getJmxNamePrefix());
if (factory == null) {
jmxUnregister(); // tidy up
throw new IllegalArgumentException("factory may not be null");
}
//赋值自定义的PooledObjectFactory实现对象
this.factory = factory;
//LinkedBlockingDeque用来维护对象池,是一个双端队列
idleObjects = new LinkedBlockingDeque<>(config.getFairness());
//设置外部动态配置参数,主要需要覆盖BaseGenericObjectPool内的参数
setConfig(config);
//设置回收线程【主要针对空闲对象和泄露对象的回收】
startEvictor(getTimeBetweenEvictionRunsMillis());
}
2.带丢弃策略的构造函数
public GenericObjectPool(final PooledObjectFactory factory,
final GenericObjectPoolConfig config, final AbandonedConfig abandonedConfig) {
//调用上述构造函数
this(factory, config);
//增加丢弃策略的配置
setAbandonedConfig(abandonedConfig);
}
1. 从链接池内获取一个新链接
public T borrowObject(final long borrowMaxWaitMillis) throws Exception {
//判断链接池是否打开
assertOpen();
//是否执行回收逻辑【长时间占用链接而没有释放的链接】
//1.removeAbandonedOnBorrow = true【默认为false】
//2.空闲链接数目 < 2
//3.(当前总链接数 - 池内链接数) > 配置的最大链接数 - 3
final AbandonedConfig ac = this.abandonedConfig;
if (ac != null && ac.getRemoveAbandonedOnBorrow() &&
(getNumIdle() < 2) &&
(getNumActive() > getMaxTotal() - 3) ) {
removeAbandoned(ac);
}
PooledObject p = null;
//获取不到链接时是否阻塞直到成功获取
final boolean blockWhenExhausted = getBlockWhenExhausted();
//新建标识
boolean create;
//借取链接时花费时间
final long waitTime = System.currentTimeMillis();
while (p == null) {
create = false;
//从链接池内获取一个空闲链接
p = idleObjects.pollFirst();
if (p == null) {
//如果链接池内获取不到,则创建一个新链接
//1.创建成功
//2.创建失败【已经达到最大链接数目,当前没法继续创建,返回null】
p = create();
if (p != null) {
//更新创建标识,表明创建成功
create = true;
}
}
//获取不到链接则阻塞等待
if (blockWhenExhausted) {
if (p == null) {
if (borrowMaxWaitMillis < 0) {
//没有超时时间,则阻塞到能获取到新链接为止
p = idleObjects.takeFirst();
} else {
//有超时时间
p = idleObjects.pollFirst(borrowMaxWaitMillis,
TimeUnit.MILLISECONDS);
}
}
//达到超时时间,则time out
if (p == null) {
throw new NoSuchElementException(
"Timeout waiting for idle object");
}
} else {
//没有阻塞时间,则抛出异常
if (p == null) {
throw new NoSuchElementException("Pool exhausted");
}
}
//更新链接的状态,变为占用
if (!p.allocate()) {
p = null;
}
if (p != null) {
try {
//尝试激活链接,需要子类自己实现自己的激活流程
factory.activateObject(p);
} catch (final Exception e) {
try {
//激活失败,则销毁当前无效链接
destroy(p);
} catch (final Exception e1) {
// Ignore - activation failure is more important
}
p = null;
if (create) {
//当前链接是新建出来的,则抛出异常,如果是从池内拿到的,无需判断
final NoSuchElementException nsee = new NoSuchElementException(
"Unable to activate object");
nsee.initCause(e);
throw nsee;
}
}
//1.借取时是否进行测试
//2.新建的是否进行测试
if (p != null && (getTestOnBorrow() || create && getTestOnCreate())) {
boolean validate = false;
Throwable validationThrowable = null;
try {
//校验链接,主要判断链接状态是否正常
validate = factory.validateObject(p);
} catch (final Throwable t) {
PoolUtils.checkRethrow(t);
validationThrowable = t;
}
if (!validate) {
try {
//不正常销毁
destroy(p);
destroyedByBorrowValidationCount.incrementAndGet();
} catch (final Exception e) {
// Ignore - validation failure is more important
}
p = null;
if (create) {
final NoSuchElementException nsee = new NoSuchElementException(
"Unable to validate object");
nsee.initCause(validationThrowable);
throw nsee;
}
}
}
}
}
//更新此链接的一些统计信息
updateStatsBorrow(p, System.currentTimeMillis() - waitTime);
return p.getObject();
}
2.create()创建对象的方法
private PooledObject create() throws Exception {
//配置的最大链接数
int localMaxTotal = getMaxTotal();
if (localMaxTotal < 0) {
localMaxTotal = Integer.MAX_VALUE;
}
//是否创建成功的一个flag
// - TRUE: 调用工厂类成功创建一个对象
// - FALSE: 返回空
// - null: 并发创建标识
Boolean create = null;
while (create == null) {
synchronized (makeObjectCountLock) {
//获取包括当前一次操作创建出的总链接数
final long newCreateCount = createCount.incrementAndGet();
if (newCreateCount > localMaxTotal) {
//表明当前容量已满,针对当前一次操作需要做特殊处理
//数目记录减一
createCount.decrementAndGet();
if (makeObjectCount == 0) {
//容量已满并且没有其他线程在创建连接对象,
//表明此次已经无法创建,返回null并等待归还的空闲对象
create = Boolean.FALSE;
} else {
//表明当前有其他线程已经在创建对象最后一个连接对象
//如果此次继续创建的话可能会超过容量大小,但是此时不能返回false,因为其他线程已经在创建了
//其他线程创建结果是未知的,因此阻塞当前线程,等待其他线程的唤醒
//唤醒之后,会继续进入while逻辑,进行下一次创建流程
makeObjectCountLock.wait();
}
} else {
//当前数目没有超过最大连接数,则可以创建
makeObjectCount++;
create = Boolean.TRUE;
}
}
}
if (!create.booleanValue()) {
//此条件只在容量已满时返回null,用于等待线程归还
return null;
}
final PooledObject p;
try {
//创建连接对象
p = factory.makeObject();
} catch (final Exception e) {
//发生异常时数目减一
createCount.decrementAndGet();
throw e;
} finally {
synchronized (makeObjectCountLock) {
makeObjectCount--;
makeObjectCountLock.notifyAll();
}
}
final AbandonedConfig ac = this.abandonedConfig;
if (ac != null && ac.getLogAbandoned()) {
p.setLogAbandoned(true);
if (p instanceof DefaultPooledObject>) {
((DefaultPooledObject) p).setRequireFullStackTrace(ac.getRequireFullStackTrace());
}
}
//计数
createdCount.incrementAndGet();
allObjects.put(new IdentityWrapper<>(p.getObject()), p);
return p;
}
1.归还一个对象至连接池
public void returnObject(final T obj) {
final PooledObject p = allObjects.get(new IdentityWrapper<>(obj));
//1.当前连接对象不是连接池对象
//2.当前连接已经被丢弃
if (p == null) {
if (!isAbandonedConfig()) {
throw new IllegalStateException(
"Returned object not currently part of this pool");
}
return;
}
synchronized(p) {
final PooledObjectState state = p.getState();
//此连接对象不是已分配状态,抛异常
if (state != PooledObjectState.ALLOCATED) {
throw new IllegalStateException(
"Object has already been returned to this pool or is invalid");
}
//标记为returning,避免被垃圾回收器标记为丢弃状态
p.markReturning();
}
//
final long activeTime = p.getActiveTimeMillis();
//是否在归还时测试连接对象
if (getTestOnReturn()) {
if (!factory.validateObject(p)) {
try {
//验证不通过销毁对象
destroy(p);
} catch (final Exception e) {
swallowException(e);
}
try {
//确保最小空闲数量
ensureIdle(1, false);
} catch (final Exception e) {
swallowException(e);
}
//更新归还的统计信息
updateStatsReturn(activeTime);
return;
}
}
try {
factory.passivateObject(p);
} catch (final Exception e1) {
swallowException(e1);
try {
destroy(p);
} catch (final Exception e) {
swallowException(e);
}
try {
ensureIdle(1, false);
} catch (final Exception e) {
swallowException(e);
}
updateStatsReturn(activeTime);
return;
}
if (!p.deallocate()) {
//变更状态
throw new IllegalStateException(
"Object has already been returned to this pool or is invalid");
}
//获取最大空闲数量
final int maxIdleSave = getMaxIdle();
if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) {
//1.连接池已关闭
//2.当前连接池空闲对象已满
//则无需归还
try {
destroy(p);
} catch (final Exception e) {
swallowException(e);
}
} else {
//根据配置的入队列规则讲连接对象放入队列内
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();
}
}
updateStatsReturn(activeTime);
}
2. ensureIdle()确保最小连接
private void ensureIdle(final int idleCount, final boolean always) throws Exception {
if (idleCount < 1 || isClosed() || (!always && !idleObjects.hasTakeWaiters())) {
//如果连接池此时有一个线程在等待获取,则由此线程保证即可
return;
}
//当池内对象 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()) {
clear();
}
}
1.evict()是空闲队列回收器或者泄露对象回收器
public void evict() throws Exception {
assertOpen();
if (idleObjects.size() > 0) {
PooledObject underTest = null;
final EvictionPolicy evictionPolicy = getEvictionPolicy();
synchronized (evictionLock) {
//获取回收期执行参数
final EvictionConfig evictionConfig = new EvictionConfig(
getMinEvictableIdleTimeMillis(),
getSoftMinEvictableIdleTimeMillis(),
getMinIdle());
//连接是否被此回收器检测
final boolean testWhileIdle = getTestWhileIdle();
//getNumTests 为一次检测几个对象,默认为3
for (int i = 0, m = getNumTests(); i < m; i++) {
//构造一个迭代器
if (evictionIterator == null || !evictionIterator.hasNext()) {
evictionIterator = new EvictionIterator(idleObjects);
}
if (!evictionIterator.hasNext()) {
return;
}
try {
underTest = evictionIterator.next();
} catch (final NoSuchElementException nsee) {
//检测时碰巧被借出,无需检测了
i--;
evictionIterator = null;
continue;
}
if (!underTest.startEvictionTest()) {
//判定此连接对象能否被检测,状态不是IDLE的不检测
i--;
continue;
}
boolean evict;
try {
//根据回收策略判断对象是否能够被回收
evict = evictionPolicy.evict(evictionConfig, underTest,
idleObjects.size());
} catch (final Throwable t) {
PoolUtils.checkRethrow(t);
swallowException(new Exception(t));
evict = false;
}
if (evict) {
//能够回收时销毁此对象
destroy(underTest);
destroyedByEvictorCount.incrementAndGet();
} else {
//没法回收时去检测
if (testWhileIdle) {
boolean active = false;
try {
//激活对象
factory.activateObject(underTest);
active = true;
} catch (final Exception e) {
//激活失败销毁
destroy(underTest);
destroyedByEvictorCount.incrementAndGet();
}
if (active) {
//激活之后验证此连接是否正常
if (!factory.validateObject(underTest)) {
//验证失败销毁
destroy(underTest);
destroyedByEvictorCount.incrementAndGet();
} else {
try {
factory.passivateObject(underTest);
} catch (final Exception e) {
destroy(underTest);
destroyedByEvictorCount.incrementAndGet();
}
}
}
}
if (!underTest.endEvictionTest(idleObjects)) {
}
}
}
}
}
//回收对象时判定是否需要回收占用对象【避免占用时间过长导致连接泄露】
final AbandonedConfig ac = this.abandonedConfig;
if (ac != null && ac.getRemoveAbandonedOnMaintenance()) {
removeAbandoned(ac);
}
}
2.evict()方法
EvictionConfig{
//空闲链接存活的最小时间,达到此值后空闲链接将被移除
private final long idleEvictTime;
//空闲链接存活的最小时间,达到此值后被移除,且要保留minIlde个空闲链接,默认为-1。
private final long idleSoftEvictTime;
//最小空闲连接
private final int minIdle;
}
public boolean evict(final EvictionConfig config, final PooledObject underTest,
final int idleCount) {
//1.空闲连接的生成时间 > 配置的存活最小时间
//2.连接池大小 > 最小空闲连接 或者 空闲连接的生成时间 > 配置存活的最小时间
if ((config.getIdleSoftEvictTime() < underTest.getIdleTimeMillis() &&
config.getMinIdle() < idleCount) ||
config.getIdleEvictTime() < underTest.getIdleTimeMillis()) {
return true;
}
return false;
}
3.removeAbandoned() 回收泄露对象
private void removeAbandoned(final AbandonedConfig ac) {
final long now = System.currentTimeMillis();
//配置回收过程的超时时间
final long timeout =
now - (ac.getRemoveAbandonedTimeout() * 1000L);
final ArrayList> remove = new ArrayList<>();
final Iterator> it = allObjects.values().iterator();
while (it.hasNext()) {
final PooledObject pooledObject = it.next();
synchronized (pooledObject) {
if (pooledObject.getState() == PooledObjectState.ALLOCATED &&
pooledObject.getLastUsedTime() <= timeout) {
//连接对象被占用时间过长,标记为回收
pooledObject.markAbandoned();
remove.add(pooledObject);
}
}
}
final Iterator> itr = remove.iterator();
while (itr.hasNext()) {
final PooledObject pooledObject = itr.next();
if (ac.getLogAbandoned()) {
pooledObject.printStackTrace(ac.getLogWriter());
}
try {
//销毁对象
invalidateObject(pooledObject.getObject());
} catch (final Exception e) {
e.printStackTrace();
}
}
}