上一篇:對象池common-pool2分析java
common-pool2策略ide
上一篇對象池common-pool2分析從三個主要的接口進行分析,這一篇將對源碼進行詳細的分析,力圖找出對象池的管理策略.從以前的分析能夠看出ObjectPool定義了對象池須要實現的功能,因此重點分析ObjectPool.this
GenericObjectPool:通常對象池spa
GenericKeyedObjectPool:能夠根據key分組的對象池.net
SoftReferenceObjectPool:軟引用對象池. 線程
GenericObjectPoolcode
public GenericObjectPool(PooledObjectFactory<T> factory, GenericObjectPoolConfig config) { super(config, ONAME_BASE, config.getJmxNamePrefix()); if (factory == null) { jmxUnregister(); // tidy up throw new IllegalArgumentException("factory may not be null"); } this.factory = factory; //根據給定的容量和策略建立空閒對象隊列,默認容量Integer.MAX_VALUE //fairness爲true時相似FIFO隊列 idleObjects = new LinkedBlockingDeque<PooledObject<T>>(config.getFairness()); //設置配置信息 setConfig(config); //根據給定延遲啓動驅逐器 startEvictor(getTimeBetweenEvictionRunsMillis()); }
BaseGenericObjectPool對象
final void startEvictor(long delay) { synchronized (evictionLock) { //若是evictor已經啓動則中止 if (null != evictor) { EvictionTimer.cancel(evictor); evictor = null; evictionIterator = null; } //當delay即timeBetweenEvictionRunsMillis大於0時根據給定的delay啓動新的驅逐器 if (delay > 0) { evictor = new Evictor(); EvictionTimer.schedule(evictor, delay, delay); } } }
BaseGenericObjectPool內部類Evictor
blog
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 { if (factoryClassLoader != null) { // Set the class loader for the factory ClassLoader cl = factoryClassLoader.get(); if (cl == null) { // The pool has been dereferenced and the class loader // GC'd. Cancel this timer so the pool can be GC'd as // well. cancel(); return; } Thread.currentThread().setContextClassLoader(cl); } // Evict from the pool try { //調用public abstract void evict() throws Exception;此方法由子類實現. 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. try { //確保對象池中空閒對象數大於等於設置的最小空閒對象數 ensureMinIdle(); } catch (Exception e) { swallowException(e); } } finally { // Restore the previous CCL Thread.currentThread().setContextClassLoader(savedClassLoader); } } }
GenericObjectPool的方法evict()接口
public void evict() throws Exception { assertOpen();//確保鏈接池是打開的 if (idleObjects.size() > 0) { PooledObject<T> underTest = null; //獲取驅逐策略 EvictionPolicy<T> evictionPolicy = getEvictionPolicy(); synchronized (evictionLock) { //驅逐配置 EvictionConfig evictionConfig = new EvictionConfig( getMinEvictableIdleTimeMillis(), getSoftMinEvictableIdleTimeMillis(), getMinIdle()); //空閒時檢查 boolean testWhileIdle = getTestWhileIdle(); //getNumTests()獲取檢測的數量 for (int i = 0, m = getNumTests(); i < m; i++) { if (evictionIterator == null || !evictionIterator.hasNext()) { if (getLifo()) {//鏈接池是不是後進先出 //返回倒序的迭代 evictionIterator = idleObjects.descendingIterator(); } else { evictionIterator = idleObjects.iterator(); } } if (!evictionIterator.hasNext()) { // Pool exhausted, nothing to do here return; } try { //獲取對象 underTest = evictionIterator.next(); } catch (NoSuchElementException nsee) { // Object was borrowed in another thread // Don't count this as an eviction test so reduce i; i--; evictionIterator = null; continue; } if (!underTest.startEvictionTest()) { // Object was borrowed in another thread // Don't count this as an eviction test so reduce i; i--; continue; } // User provided eviction policy could throw all sorts of // crazy exceptions. Protect against such an exception // killing the eviction thread. boolean evict; try { //檢測對象池裏的空閒對象是否應該被驅逐 evict = evictionPolicy.evict(evictionConfig, underTest, idleObjects.size()); } catch (Throwable t) { // Slightly convoluted as SwallowedExceptionListener // uses Exception rather than Throwable PoolUtils.checkRethrow(t); swallowException(new Exception(t)); // Don't evict on error conditions evict = false; } if (evict) { destroy(underTest);//銷燬 destroyedByEvictorCount.incrementAndGet(); } else { if (testWhileIdle) { boolean active = false; try { factory.activateObject(underTest);//激活 active = true; } catch (Exception e) { destroy(underTest);//激活異常則銷燬 destroyedByEvictorCount.incrementAndGet(); } if (active) {//已經激活 if (!factory.validateObject(underTest)) {//驗證不經過則銷燬 destroy(underTest); destroyedByEvictorCount.incrementAndGet(); } else { try { factory.passivateObject(underTest);//鈍化 } catch (Exception e) { destroy(underTest); destroyedByEvictorCount.incrementAndGet(); } } } } if (!underTest.endEvictionTest(idleObjects)) { // TODO - May need to add code here once additional // states are used } } } } } AbandonedConfig ac = this.abandonedConfig; if (ac != null && ac.getRemoveAbandonedOnMaintenance()) { removeAbandoned(ac); } }
GenericKeyedObjectPool
與GenericObjectPool相似,只是須要遍歷key,根據key獲取空閒對象.
SoftReferenceObjectPool
若是一個對象只具備軟引用,則內存空間足夠,垃圾回收器就不會回收它;若是內存空間不足了,就會回收這些對象的內存。SoftReferenceObjectPool沒有後臺驅逐線程,當內存不足時由虛擬機清除.