📄 genericobjectpool.java
字号:
* discard references to returned objects and ensure that an object is not * returned to the pool multiple times in sequence (i.e., without being * borrowed again between returns). Violating this contract will result in * the same object appearing multiple times in the pool and pool counters * (numActive, numIdle) returning incorrect values.</p> */ public void returnObject(Object obj) throws Exception { try { addObjectToPool(obj, true); } catch (Exception e) { if (_factory != null) { try { _factory.destroyObject(obj); } catch (Exception e2) { } } }finally{ lock.lock(); try { _numActive--; }finally{ lock.unlock(); } } } /** * * @param obj * @param decrementNumActive 表示不减少活动得对象,此时只有一种可能是:Pool内部自动调整对象池大小 * * @throws Exception */ private void addObjectToPool(Object obj, boolean decrementNumActive) throws Exception { boolean success = true; /** * 如果是自动调整对象池得,则需要检测最新创建得对象是否是有效得 */ if( (!decrementNumActive||_testOnReturn) && !(_factory.validateObject(obj))) { success = false; } else { _factory.passivateObject(obj); } boolean shouldDestroy = !success; // Add instance to pool if there is room and it has passed validation // (if testOnreturn is set) lock.lock(); try { if (isClosed()) { shouldDestroy = true; } else { if((_maxIdle >= 0) && (_pool.size() >= _maxIdle)) { shouldDestroy = true; } else if(success) { // borrowObject always takes the first element from the queue, // so for LIFO, push on top, FIFO add to end if (_lifo) { _pool.addFirst(new ObjectTimestampPair(obj)); } else { _pool.addLast(new ObjectTimestampPair(obj)); } } } }finally{ lock.unlock(); } if(success){ if(_whenExhaustedAction == WHEN_EXHAUSTED_BLOCK) { synchronized(this){ this.notifyAll(); } } } // Destroy the instance if necessary if(shouldDestroy) { try { _factory.destroyObject(obj); } catch(Exception e) { // ignored } } } public void close() throws Exception { super.close(); synchronized (this) { clear(); startEvictor(-1L); } } /** * Sets the {@link PoolableObjectFactory factory} this pool uses * to create new instances. Trying to change * the <code>factory</code> while there are borrowed objects will * throw an {@link IllegalStateException}. * * @param factory the {@link PoolableObjectFactory} used to create new instances. * @throws IllegalStateException when the factory cannot be set at this time */ public synchronized void setFactory(PoolableObjectFactory factory) throws IllegalStateException { assertOpen(); if(0 < getNumActive()) { throw new IllegalStateException("Objects are already active"); } else { clear(); _factory = factory; } } /** * <p>Perform <code>numTests</code> idle object eviction tests, evicting * examined objects that meet the criteria for eviction. If * <code>testWhileIdle</code> is true, examined objects are validated * when visited (and removed if invalid); otherwise only objects that * have been idle for more than <code>minEvicableIdletimeMillis</code> * are removed.</p> * * <p>Successive activations of this method examine objects in * in sequence, cycling through objects in oldest-to-youngest order.</p> * * @throws Exception if the pool is closed or eviction fails. */ public synchronized void evict() throws Exception { assertOpen(); if(!_pool.isEmpty()) { if (null == _evictionCursor) { _evictionCursor = (_pool.cursor(_lifo ? _pool.size() : 0)); } for (int i=0,m=getNumTests();i<m;i++) { if ((_lifo && !_evictionCursor.hasPrevious()) || !_lifo && !_evictionCursor.hasNext()) { _evictionCursor.close(); _evictionCursor = _pool.cursor(_lifo ? _pool.size() : 0); } boolean removeObject = false; final ObjectTimestampPair pair = _lifo ? (ObjectTimestampPair) _evictionCursor.previous() : (ObjectTimestampPair) _evictionCursor.next(); final long idleTimeMilis = System.currentTimeMillis() - pair.tstamp; if ((_minEvictableIdleTimeMillis > 0) && (idleTimeMilis > _minEvictableIdleTimeMillis)) { removeObject = true; } else if ((_softMinEvictableIdleTimeMillis > 0) && (idleTimeMilis > _softMinEvictableIdleTimeMillis) && (getNumIdle() > getMinIdle())) { removeObject = true; } if(_testWhileIdle && !removeObject) { boolean active = false; try { _factory.activateObject(pair.value); active = true; } catch(Exception e) { removeObject=true; } if(active) { if(!_factory.validateObject(pair.value)) { removeObject=true; } else { try { _factory.passivateObject(pair.value); } catch(Exception e) { removeObject=true; } } } } if(removeObject) { try { _evictionCursor.remove(); _factory.destroyObject(pair.value); } catch(Exception e) { // ignored } } } } // if !empty } /** * Check to see if we are below our minimum number of objects * if so enough to bring us back to our minimum. * * @throws Exception when {@link #addObject()} fails. */ private void ensureMinIdle() throws Exception { // this method isn't synchronized so the // calculateDeficit is done at the beginning // as a loop limit and a second time inside the loop // to stop when another thread already returned the // needed objects int objectDeficit = calculateDeficit(); for ( int j = 0 ; j < objectDeficit && calculateDeficit() > 0 ; j++ ) { addObject(); } } private synchronized int calculateDeficit() { int objectDeficit = getMinIdle() - getNumIdle(); if (_maxActive > 0) { int growLimit = Math.max(0, getMaxActive() - getNumActive() - getNumIdle()); objectDeficit = Math.min(objectDeficit, growLimit); } return objectDeficit; } /** * Create an object, and place it into the pool. * addObject() is useful for "pre-loading" a pool with idle objects. */ public void addObject() throws Exception { assertOpen(); if (_factory == null) { throw new IllegalStateException("Cannot add objects without a factory."); } Object obj = _factory.makeObject(); try { assertOpen(); addObjectToPool(obj, false); } catch (IllegalStateException ex) { // Pool closed try { _factory.destroyObject(obj); } catch (Exception ex2) { // swallow } throw ex; } } //--- non-public methods ---------------------------------------- /** * Start the eviction thread or service, or when * <i>delay</i> is non-positive, stop it * if it is already running. * * @param delay milliseconds between evictor runs. */ protected synchronized void startEvictor(long delay) { if(null != _evictor) { EvictionTimer.cancel(_evictor); _evictor = null; } if(delay > 0) { _evictor = new Evictor(); EvictionTimer.schedule(_evictor, delay, delay); } } synchronized String debugInfo() { StringBuffer buf = new StringBuffer(); buf.append("Active: ").append(getNumActive()).append("\n"); buf.append("Idle: ").append(getNumIdle()).append("\n"); buf.append("Idle Objects:\n"); Iterator it = _pool.iterator(); long time = System.currentTimeMillis(); while(it.hasNext()) { ObjectTimestampPair pair = (ObjectTimestampPair)(it.next()); buf.append("\t").append(pair.value).append("\t").append(time - pair.tstamp).append("\n"); } return buf.toString(); } private int getNumTests() { if(_numTestsPerEvictionRun >= 0) { return Math.min(_numTestsPerEvictionRun, _pool.size()); } else { return(int)(Math.ceil((double)_pool.size()/Math.abs((double)_numTestsPerEvictionRun))); } } //--- inner classes ---------------------------------------------- /** * The idle object evictor {@link TimerTask}. * @see GenericObjectPool#setTimeBetwee
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -