📄 generickeyedobjectpool.java
字号:
}
/**
* When <tt>true</tt>, objects will be
* {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
* by the idle object evictor (if any). If an object
* fails to validate, it will be dropped from the pool.
*
* @see #getTestWhileIdle
* @see #setTimeBetweenEvictionRunsMillis
*/
public synchronized void setTestWhileIdle(boolean testWhileIdle) {
_testWhileIdle = testWhileIdle;
}
/**
* Sets my configuration.
* @see GenericKeyedObjectPool.Config
*/
public synchronized void setConfig(GenericKeyedObjectPool.Config conf) {
setMaxIdle(conf.maxIdle);
setMaxActive(conf.maxActive);
setMaxTotal(conf.maxTotal);
setMaxWait(conf.maxWait);
setWhenExhaustedAction(conf.whenExhaustedAction);
setTestOnBorrow(conf.testOnBorrow);
setTestOnReturn(conf.testOnReturn);
setTestWhileIdle(conf.testWhileIdle);
setNumTestsPerEvictionRun(conf.numTestsPerEvictionRun);
setMinEvictableIdleTimeMillis(conf.minEvictableIdleTimeMillis);
setTimeBetweenEvictionRunsMillis(conf.timeBetweenEvictionRunsMillis);
}
//-- ObjectPool methods ------------------------------------------
public synchronized Object borrowObject(Object key) throws Exception {
long starttime = System.currentTimeMillis();
boolean newlyCreated = false;
for(;;) {
CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.get(key));
if(null == pool) {
pool = new CursorableLinkedList();
_poolMap.put(key,pool);
_poolList.add(key);
}
ObjectTimestampPair pair = null;
// if there are any sleeping, just grab one of those
try {
pair = (ObjectTimestampPair)(pool.removeFirst());
if(null != pair) {
_totalIdle--;
}
} catch(NoSuchElementException e) { /* ignored */
}
// otherwise
if(null == pair) {
// if there is a totalMaxActive and we are at the limit then
// we have to make room
// TODO: this could be improved by only removing the oldest object
if ((_maxTotal > 0) && (_totalActive + _totalIdle >= _maxTotal)) {
clear();
}
// check if we can create one
// (note we know that the num sleeping is 0, else we wouldn't be here)
int active = getActiveCount(key);
if ((_maxActive <= 0 || active < _maxActive) &&
(_maxTotal <= 0 || _totalActive + _totalIdle < _maxTotal)) {
Object obj = _factory.makeObject(key);
pair = new ObjectTimestampPair(obj);
newlyCreated = true;
} else {
// the pool is exhausted
switch(_whenExhaustedAction) {
case WHEN_EXHAUSTED_GROW:
Object obj = _factory.makeObject(key);
pair = new ObjectTimestampPair(obj);
break;
case WHEN_EXHAUSTED_FAIL:
throw new NoSuchElementException();
case WHEN_EXHAUSTED_BLOCK:
try {
if(_maxWait <= 0) {
wait();
} else {
wait(_maxWait);
}
} catch(InterruptedException e) {
// ignored
}
if(_maxWait > 0 && ((System.currentTimeMillis() - starttime) >= _maxWait)) {
throw new NoSuchElementException("Timeout waiting for idle object");
} else {
continue; // keep looping
}
default:
throw new IllegalArgumentException("whenExhaustedAction " + _whenExhaustedAction + " not recognized.");
}
}
}
_factory.activateObject(key,pair.value);
if(_testOnBorrow && !_factory.validateObject(key,pair.value)) {
_factory.destroyObject(key,pair.value);
if(newlyCreated) {
throw new NoSuchElementException("Could not create a validated object");
} // else keep looping
} else {
incrementActiveCount(key);
return pair.value;
}
}
}
public synchronized void clear() {
for(Iterator keyiter = _poolList.iterator(); keyiter.hasNext(); ) {
Object key = keyiter.next();
CursorableLinkedList list = (CursorableLinkedList)(_poolMap.get(key));
for(Iterator it = list.iterator(); it.hasNext(); ) {
try {
_factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value);
} catch(Exception e) {
// ignore error, keep destroying the rest
}
it.remove();
}
}
_poolMap.clear();
_poolList.clear();
_totalIdle = 0;
notifyAll();
}
public synchronized void clear(Object key) {
CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.remove(key));
if(null == pool) {
return;
} else {
_poolList.remove(key);
for(Iterator it = pool.iterator(); it.hasNext(); ) {
try {
_factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value);
} catch(Exception e) {
// ignore error, keep destroying the rest
}
it.remove();
_totalIdle--;
}
}
notifyAll();
}
public synchronized int getNumActive() {
return _totalActive;
}
public synchronized int getNumIdle() {
return _totalIdle;
}
public synchronized int getNumActive(Object key) {
return getActiveCount(key);
}
public synchronized int getNumIdle(Object key) {
try {
return((CursorableLinkedList)(_poolMap.get(key))).size();
} catch(Exception e) {
return 0;
}
}
public void returnObject(Object key, Object obj) throws Exception {
// if we need to validate this object, do so
boolean success = true; // whether or not this object passed validation
if(_testOnReturn && !_factory.validateObject(key, obj)) {
success = false;
try {
_factory.destroyObject(key, obj);
} catch(Exception e) {
// ignored
}
} else {
try {
_factory.passivateObject(key, obj);
} catch(Exception e) {
success = false;
}
}
boolean shouldDestroy = false;
synchronized(this) {
// grab the pool (list) of objects associated with the given key
CursorableLinkedList pool = (CursorableLinkedList) (_poolMap.get(key));
// if it doesn't exist, create it
if(null == pool) {
pool = new CursorableLinkedList();
_poolMap.put(key, pool);
_poolList.add(key);
}
decrementActiveCount(key);
// if there's no space in the pool, flag the object for destruction
// else if we passivated succesfully, return it to the pool
if(_maxIdle >= 0 && (pool.size() >= _maxIdle)) {
shouldDestroy = true;
} else if(success) {
pool.addFirst(new ObjectTimestampPair(obj));
_totalIdle++;
}
notifyAll();
}
if(shouldDestroy) {
try {
_factory.destroyObject(key, obj);
} catch(Exception e) {
// ignored?
}
}
}
public void invalidateObject(Object key, Object obj) throws Exception {
try {
_factory.destroyObject(key, obj);
}
finally {
synchronized(this) {
decrementActiveCount(key);
notifyAll(); // _totalActive has changed
}
}
}
public void addObject(Object key) throws Exception {
Object obj = _factory.makeObject(key);
synchronized(this) {
incrementActiveCount(key); // returnObject will decrement this
returnObject(key,obj);
}
}
public synchronized void close() throws Exception {
clear();
_poolList = null;
_poolMap = null;
_activeMap = null;
if(null != _evictionCursor) {
_evictionCursor.close();
_evictionCursor = null;
}
if(null != _evictionKeyCursor) {
_evictionKeyCursor.close();
_evictionKeyCursor = null;
}
if(null != _evictor) {
_evictor.cancel();
_evictor = null;
}
}
public synchronized void setFactory(KeyedPoolableObjectFactory factory) throws IllegalStateException {
if(0 < getNumActive()) {
throw new IllegalStateException("Objects are already active");
} else {
clear();
_factory = factory;
}
}
public synchronized void evict() throws Exception {
Object key = null;
for(int i=0,m=getNumTests();i<m;i++) {
if(_poolMap.size() > 0) {
// if we don't have a key cursor, then create one, and close any object cursor
if(null == _evictionKeyCursor) {
_evictionKeyCursor = _poolList.cursor();
key = null;
if(null != _evictionCursor) {
_evictionCursor.close();
_evictionCursor = null;
}
}
// if we don't have an object cursor
if(null == _evictionCursor) {
// if the _evictionKeyCursor has a next value, then use it
if(_evictionKeyCursor.hasNext()) {
key = _evictionKeyCursor.next();
CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.get(key));
_evictionCursor = pool.cursor(pool.size());
} else {
// else close the key cursor and loop back around
if(null != _evictionKeyCursor) {
_evictionKeyCursor.close();
_evictionKeyCursor = _poolList.cursor();
if(null != _evictionCursor) {
_evictionCursor.close();
_evictionCursor = null;
}
}
continue;
}
}
// if the _evictionCursor has a previous object, then test it
if(_evictionCursor.hasPrevious()) {
ObjectTimestampPair pair = (ObjectTimestampPair)(_evictionCursor.previous());
boolean removeObject=false;
if(_minEvictableIdleTimeMillis > 0 &&
System.currentTimeMillis() - pair.tstamp > _minEvictableIdleTimeMillis) {
removeObject=true;
} else if(_testWhileIdle) {
boolean active = false;
try {
_factory.activateObject(key,pair.value);
active = true;
} catch(Exception e) {
removeObject=true;
}
if(active) {
if(!_factory.validateObject(key,pair.value)) {
removeObject=true;
} else {
try {
_factory.passivateObject(key,pair.value);
} catch(Exception e) {
removeObject=true;
}
}
}
}
if(removeObject) {
try {
_evictionCursor.remove();
_totalIdle--;
_factory.destroyObject(key,pair.value);
// if that was the last object for that key, drop that pool
if( ((CursorableLinkedList)(_poolMap.get(key))).isEmpty() ) {
_poolMap.remove(key);
_poolList.remove(key);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -