说明
有几种实现ObjectPool实现,这里讲解具有代表性的GenericObjectPool
下面的活动图是intellij + graphviz + plantUML画的
可能细节上并不是很精确,不过无伤大雅
有些代码少量,但是有需要注意的地方,就直接贴代码了
主要的函数如下
borrowObject();//从pool中借出pooledObject
returnObject(T obj);//将pooledObject还给pool
removeAbandoned(AbandonedConfig ac);//Abandon操作,处理allocated状态闲置过久的对象
public void evict() throws Exception;//根据timer定时进行"驱逐",处理idle对象
属性说明
讲几个属性
//记录PooledObject的双端队列,根据config的lifo规则判断加入队首或者尾,取出都是从头取
private final LinkedBlockingDeque<PooledObject<T>> idleObjects;
//记录T到对应封装的PooledObject的关系
private final Map<T, PooledObject<T>> allObjects= new ConcurrentHashMap<T, PooledObject<T>>();
方法说明
borrowObject
removeAbandoned后面会介绍
备注:
1.为什么pool有destroy方法,和factory的invalidate方法有什么关系
调用上,是包含的关系,另外更新一些记录,见下
destroy
private void destroy(PooledObject<T> toDestory) throws Exception {
//钝化,默认实现是将其标记为INVALID
toDestory.invalidate();
//从队列中删掉
idleObjects.remove(toDestory);
allObjects.remove(toDestory.getObject());
try {
//工厂进行需要时实现
factory.destroyObject(toDestory);
} finally {
destroyedCount.incrementAndGet();
createCount.decrementAndGet();
}
}
removeAbandoned
invalidateObject如下
invalidateObject
@Override
public void invalidateObject(T obj) throws Exception {
PooledObject<T> p = allObjects.get(obj);
if (p == null) {
if (isAbandonedConfig()) {
return;
} else {
throw new IllegalStateException(
"Invalidated object not currently part of this pool");
}
}
synchronized (p) {
//这里控制并发,如果对象还没有处于INVALID状态(只有destroy会将其变为INVALID)
//那么就destroy掉
if (p.getState() != PooledObjectState.INVALID) {
destroy(p);
}
}
ensureIdle(1, false);
}
这样控制并发,代码上总觉得会有问题
ensureIdle
//参数,状态有意义,然后没有线程等着取idle queue时,根据always判断是否要保证至少存活idleCount个pooledObject
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;
}
//如果是last in first out
if (getLifo()) {
idleObjects.addFirst(p);
} else {
idleObjects.addLast(p);
}
}
}
returnObject
备注:
1.如果存在abandonedConfig,那么正常分配的资源可能由于一段时间没有用而被丢掉(removeAbandon里调用invalidObject,调用了destroy进行了allObjects.remove),成为null,所以此时不抛异常
2.正常分配资源的状态都会为ALLOCATED,因此return的时候要检查是不是该状态
3.如果没有遇到异常情况,最后会根据当前idle数量和config允许的最大idle数量,
如果超出了,则毁掉,否则重新加入双端队列
evict
备注:
1.evict有两层策略
对象本身的evict test(可以理解为局部evict)
evictPolicy根据EvictionConfig的软标准,硬标准进行判断是否evict(可以理解为全局evict)
思考
1.allObjects什么时候put,什么时候remove
只有GenericObjectPool#create时候才put
只有GenericObjectPool#destroy
2.evict机制理解:
进行evict时,要经历
pooledObject自己的evict:如startEvictionTest
又要经历evictPolicy的evict
从设计的角度上说无可厚非,可以说是局部判断evict和全局判断evict
问题
1.局部判断evict到底是有什么用,除了标记状态变化以外,和PooledObjectFactory#validateObject功能上什么区别???