锁定老帖子 主题:Commons Pool源码简洁分析
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (1)
|
|
---|---|
作者 | 正文 |
发表时间:2009-09-16
最后修改:2009-09-16
代码是前段时间看的(Commons Pool还是很容易理解的),昨天有时间就整理了下···原文见博客吧~
对象池(对Apache Commons部分源码分析) 1,commons pool中的StatckObjectPool 和 ReferenceObjectPool等 本身设计的确实不允许"脏"对象的外围的activate(), passivate()充当了"清理"工作..
2,如果pool的_maxSleeping阀值设置不当的话,在多线程APP下确实会导致堵塞...上限阀值和下限阀值很重要吧... 3,另外commons提供了一个ReferenceObjectPool,这种的好处在于内存不足时,GC无条件回收pool中的空闲对象,.这样资源可适当得到利用..不过pool中总要有一定量的闲对象,不可能每次都new吧。 4,commons中,是borrow()时,如果pool中没有空闲obj的时候,就创建新的obj,当然这个新对象是无状态的,所以建立在pool存储也需要建立在"无状态对象"的基本之上...
什么时候不要池化? 采用对象池化的本意,是要通过减少对象生成的次数,减少花在对象初始化上面的开销,然而池化处理本身也要付出代价,因此,并非任何情况下都适合采用对象池化。
Dr. Cliff Click在JavaOne 2003上发表的《Performance Myths Exposed》中测试表明:
1#类似Point这样的轻量级对象,进行池化处理后,性能反而下降. 2#类似Point这样的轻量级对象,进行池化处理后,性能反而下降. 3#类似JPanel\Connection这样的重量级对象,进行池化处理后,性能有所上升,可以考虑池化。
设计结构: 1,PoolableObjectFactory用于管理被池化的对象的产生、激活、挂起、校验和销毁;
2,ObjectPool用于管理要被池化的对象的借出和归还,并通知PoolableObjectFactory完成相应的工作;
设计重点:
接口设计代码(对原设计有做简化): 清单:
以下是CommonsPool的接口,也就是最抽象的一层; 1、ObjectPool.java(pool的基本接口) 2、PoolableObjectFactory.java(Factory的基本接口) #######################ObjectPool.java###############
package pools.inter; import java.util.NoSuchElementException; import pools.impl.pool.BaseObjectPool; /** * A pooling interface. * * * @author Rodney Waldhoff * @author Sandy McArthur * @since Pool 1.0 */ public interface ObjectPool { // 从池中拿裸对象 Object borrowObject() throws Exception, NoSuchElementException, IllegalStateException; // 返回给池 void returnObject(Object obj) throws Exception; // 销毁对象,需要Factory(因为设计Factory就是负责对象处理等) void invalidateObject(Object obj) throws Exception; // 利用Factory创建一个新对象 void addObject() throws Exception, IllegalStateException, UnsupportedOperationException; // 获得池中对象个数 int getNumIdle() throws UnsupportedOperationException; // 获取池外活动的对象个数 int getNumActive() throws UnsupportedOperationException; // 清空池中对象,就是把所有对象丢给Factory来销毁 void clear() throws Exception, UnsupportedOperationException; // 关闭池,但不销毁对象 void close() throws Exception; void setFactory(PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException; }
#######################PoolableObjectFactory.java###############
public interface PoolableObjectFactory { Object makeObject() throws Exception; void destroyObject(Object obj) throws Exception; boolean validateObject(Object obj); void activateObject(Object obj) throws Exception; void passivateObject(Object obj) throws Exception; }
实现设计: 清单:
1\BaseObjectPool.java 2\SoftReferenceObjectPool.java 3\StackObjectPool.java
以下是一个抽象类而已,关联的是上面的那个接口,注释同上 ######################BaseObjectPool.java################# public abstract class BaseObjectPool implements ObjectPool { public abstract Object borrowObject() throws Exception; public abstract void returnObject(Object obj) throws Exception; public abstract void invalidateObject(Object obj) throws Exception; public int getNumIdle() throws UnsupportedOperationException { return -1; } public int getNumActive() throws UnsupportedOperationException { return -1; } public void clear() throws Exception, UnsupportedOperationException { throw new UnsupportedOperationException(); } public void addObject() throws Exception, UnsupportedOperationException { throw new UnsupportedOperationException(); } public void close() throws Exception { closed = true; } public void setFactory(PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { throw new UnsupportedOperationException(); } protected final boolean isClosed() { return closed; } protected final void assertOpen() throws IllegalStateException { if (isClosed()) { throw new IllegalStateException("Pool not open"); } } /** Whether or not the pool is closed */ private volatile boolean closed = false; }
######################SoftReferenceObjectPool.java############# 一个弱引用对象池的实现类,这个对象池的特点是内存不足时,GC无条件回收池中的对象.
public class SoftReferenceObjectPool extends BaseObjectPool implements ObjectPool { public static int DEFAULT_INIT_SLEEPING_CAPACITY; public static int DEFAULT_MAX_SLEEPING; public SoftReferenceObjectPool() { _pool = new ArrayList(); // 能看出来,池中的对象是用List数据结构来存储的 _factory = null; } public SoftReferenceObjectPool(PoolableObjectFactory factory) { _pool = new ArrayList(); _factory = factory; } public SoftReferenceObjectPool(PoolableObjectFactory _factory2, int sleeping, int capacity) { // TODO Auto-generated constructor stub } public synchronized Object borrowObject() throws Exception { assertOpen(); Object obj = null; boolean newlyCreated = false; while(null == obj) { if(_pool.isEmpty()) { if(null == _factory) { throw new NoSuchElementException(); } else { newlyCreated = true; obj = _factory.makeObject(); } } else { SoftReference ref = (SoftReference)(_pool.remove(_pool.size() - 1)); obj = ref.get(); ref.clear(); // prevent this ref from being enqueued with refQueue. } if (null != _factory && null != obj) { try { _factory.activateObject(obj); if (!_factory.validateObject(obj)) { throw new Exception("ValidateObject failed"); } } catch (Throwable t) { try { _factory.destroyObject(obj); } catch (Throwable t2) { // swallowed } finally { obj = null; } if (newlyCreated) { throw new NoSuchElementException( "Could not create a validated object, cause: " + t.getMessage()); } } } } _numActive++; return obj; } public synchronized void returnObject(Object obj) throws Exception { boolean success = !isClosed(); if (_factory != null) { if(!_factory.validateObject(obj)) { success = false; } else { try { _factory.passivateObject(obj); } catch(Exception e) { success = false; } } } boolean shouldDestroy = !success; _numActive--; if(success) { _pool.add(new SoftReference(obj, refQueue)); } notifyAll(); // _numActive has changed if (shouldDestroy && _factory != null) { try { _factory.destroyObject(obj); } catch(Exception e) { // ignored } } } public synchronized void invalidateObject(Object obj) throws Exception { _numActive--; if (_factory != null) { _factory.destroyObject(obj); } notifyAll(); // _numActive has changed } /** * Create an object, and place it into the pool. * addObject() is useful for "pre-loading" a pool with idle objects. */ public synchronized void addObject() throws Exception { assertOpen(); if (_factory == null) { throw new IllegalStateException("Cannot add objects without a factory."); } Object obj = _factory.makeObject(); boolean success = true; if(!_factory.validateObject(obj)) { success = false; } else { _factory.passivateObject(obj); } boolean shouldDestroy = !success; if(success) { _pool.add(new SoftReference(obj, refQueue)); notifyAll(); // _numActive has changed } if(shouldDestroy) { try { _factory.destroyObject(obj); } catch(Exception e) { // ignored } } } /** Returns an approximation not less than the of the number of idle instances in the pool. */ public synchronized int getNumIdle() { pruneClearedReferences(); return _pool.size(); } public synchronized int getNumActive() { return _numActive; } /** * Clears any objects sitting idle in the pool. */ public synchronized void clear() { if(null != _factory) { Iterator iter = _pool.iterator(); while(iter.hasNext()) { try { Object obj = ((SoftReference)iter.next()).get(); if(null != obj) { _factory.destroyObject(obj); } } catch(Exception e) { // ignore error, keep destroying the rest } } } _pool.clear(); pruneClearedReferences(); } public void close() throws Exception { super.close(); clear(); } public synchronized void setFactory(PoolableObjectFactory factory) throws IllegalStateException { assertOpen(); if(0 < getNumActive()) { throw new IllegalStateException("Objects are already active"); } else { clear(); _factory = factory; } } private void pruneClearedReferences() { Reference ref; while ((ref = refQueue.poll()) != null) { try { _pool.remove(ref); } catch (UnsupportedOperationException uoe) { // ignored } } } /** My pool. */ private List _pool = null; /** My {@link PoolableObjectFactory}. */ private PoolableObjectFactory _factory = null; private final ReferenceQueue refQueue = new ReferenceQueue(); /** Number of active objects. */ private int _numActive = 0; }
########################StackObjectPool.java############# 以下是一个Stack容器的对象池
public class StackObjectPool extends BaseObjectPool implements ObjectPool { public StackObjectPool() { this((PoolableObjectFactory)null,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY); } public StackObjectPool(int maxIdle) { this((PoolableObjectFactory)null,maxIdle,DEFAULT_INIT_SLEEPING_CAPACITY); } public StackObjectPool(int maxIdle, int initIdleCapacity) { this((PoolableObjectFactory)null,maxIdle,initIdleCapacity); } public StackObjectPool(PoolableObjectFactory factory) { this(factory,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY); } public StackObjectPool(PoolableObjectFactory factory, int maxIdle) { this(factory,maxIdle,DEFAULT_INIT_SLEEPING_CAPACITY); } public StackObjectPool(PoolableObjectFactory factory, int maxIdle, int initIdleCapacity) { _factory = factory; _maxSleeping = (maxIdle < 0 ? DEFAULT_MAX_SLEEPING : maxIdle); int initcapacity = (initIdleCapacity < 1 ? DEFAULT_INIT_SLEEPING_CAPACITY : initIdleCapacity); _pool = new Stack(); _pool.ensureCapacity( initcapacity > _maxSleeping ? _maxSleeping : initcapacity); } public synchronized Object borrowObject() throws Exception { assertOpen(); Object obj = null; boolean newlyCreated = false; while (null == obj) { if (!_pool.empty()) { obj = _pool.pop(); } else { if(null == _factory) { throw new NoSuchElementException(); } else { obj = _factory.makeObject(); newlyCreated = true; if (obj == null) { throw new NoSuchElementException("PoolableObjectFactory.makeObject() returned null."); } } } if (null != _factory && null != obj) { try { _factory.activateObject(obj); if (!_factory.validateObject(obj)) { throw new Exception("ValidateObject failed"); } } catch (Throwable t) { try { _factory.destroyObject(obj); } catch (Throwable t2) { // swallowed } finally { obj = null; } if (newlyCreated) { throw new NoSuchElementException( "Could not create a validated object, cause: " + t.getMessage()); } } } } _numActive++; return obj; } public synchronized void returnObject(Object obj) throws Exception { boolean success = !isClosed(); if(null != _factory) { if(!_factory.validateObject(obj)) { success = false; } else { try { _factory.passivateObject(obj); } catch(Exception e) { success = false; } } } boolean shouldDestroy = !success; _numActive--; if (success) { Object toBeDestroyed = null; if(_pool.size() >= _maxSleeping) { shouldDestroy = true; toBeDestroyed = _pool.remove(0); // remove the stalest object } _pool.push(obj); obj = toBeDestroyed; // swap returned obj with the stalest one so it can be destroyed } notifyAll(); // _numActive has changed if(shouldDestroy) { // by constructor, shouldDestroy is false when _factory is null try { _factory.destroyObject(obj); } catch(Exception e) { // ignored } } } public synchronized void invalidateObject(Object obj) throws Exception { _numActive--; if (null != _factory) { _factory.destroyObject(obj); } notifyAll(); // _numActive has changed } public synchronized int getNumIdle() { return _pool.size(); } public synchronized int getNumActive() { return _numActive; } /** * Clears any objects sitting idle in the pool. */ public synchronized void clear() { if(null != _factory) { Iterator it = _pool.iterator(); while(it.hasNext()) { try { _factory.destroyObject(it.next()); } catch(Exception e) { // ignore error, keep destroying the rest } } } _pool.clear(); } public void close() throws Exception { super.close(); clear(); } public synchronized void addObject() throws Exception { assertOpen(); if (_factory == null) { throw new IllegalStateException("Cannot add objects without a factory."); } Object obj = _factory.makeObject(); boolean success = true; if(!_factory.validateObject(obj)) { success = false; } else { _factory.passivateObject(obj); } boolean shouldDestroy = !success; if (success) { Object toBeDestroyed = null; if(_pool.size() >= _maxSleeping) { shouldDestroy = true; toBeDestroyed = _pool.remove(0); // remove the stalest object } _pool.push(obj); obj = toBeDestroyed; // swap returned obj with the stalest one so it can be destroyed } notifyAll(); // _numIdle has changed if(shouldDestroy) { // by constructor, shouldDestroy is false when _factory is null try { _factory.destroyObject(obj); } catch(Exception e) { // ignored } } } public synchronized void setFactory(PoolableObjectFactory factory) throws IllegalStateException { assertOpen(); if(0 < getNumActive()) { throw new IllegalStateException("Objects are already active"); } else { clear(); _factory = factory; } } /** The default cap on the number of "sleeping" instances in the pool. */ public static final int DEFAULT_MAX_SLEEPING = 8; public static final int DEFAULT_INIT_SLEEPING_CAPACITY = 4; /** My pool. */ protected Stack _pool = null; /** My {@link PoolableObjectFactory}. */ protected PoolableObjectFactory _factory = null; /** The cap on the number of "sleeping" instances in the pool. */ protected int _maxSleeping = DEFAULT_MAX_SLEEPING; /** Number of object borrowed but not yet returned to the pool. */ protected int _numActive = 0; }
工厂实现代码:
清单: 1、BasePoolableObjectFactory.java 2\SoftReferencePoolFactory.java 3\StackObjectPoolFactory.java
#############################BasePoolableObjectFactory.java########## public abstract class BasePoolableObjectFactory implements PoolableObjectFactory { public abstract Object makeObject() throws Exception; /** No-op. */ public void destroyObject(Object obj) throws Exception { } /** * This implementation always returns <tt>true</tt>. * @return <tt>true</tt> */ public boolean validateObject(Object obj) { return true; } /** No-op. */ public void activateObject(Object obj) throws Exception { } /** No-op. */ public void passivateObject(Object obj) throws Exception { } }
#########################SoftReferencePoolFactory.java###########
public class SoftReferencePoolFactory implements PoolableObjectFactory { /** * Create a new StackObjectPoolFactory. * * @see StackObjectPool#StackObjectPool() */ public SoftReferencePoolFactory() { this((PoolableObjectFactory)null,StackObjectPool.DEFAULT_MAX_SLEEPING,StackObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY); } /** * Create a new StackObjectPoolFactory. * * @param maxIdle cap on the number of "sleeping" instances in the pool. * @see StackObjectPool#StackObjectPool(int) */ public SoftReferencePoolFactory(int maxIdle) { this((PoolableObjectFactory)null,maxIdle,StackObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY); } /** * Create a new StackObjectPoolFactory. * * @param maxIdle cap on the number of "sleeping" instances in the pool. * @param initIdleCapacity - initial size of the pool (this specifies the size of the container, it does not cause the pool to be pre-populated.) * @see StackObjectPool#StackObjectPool(int, int) */ public SoftReferencePoolFactory(int maxIdle, int initIdleCapacity) { this((PoolableObjectFactory)null,maxIdle,initIdleCapacity); } /** * Create a new StackObjectPoolFactory. * * @param factory the PoolableObjectFactory used by created pools. * @see StackObjectPool#StackObjectPool(PoolableObjectFactory) */ public SoftReferencePoolFactory(PoolableObjectFactory factory) { this(factory,StackObjectPool.DEFAULT_MAX_SLEEPING,StackObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY); } /** * Create a new StackObjectPoolFactory. * * @param factory the PoolableObjectFactory used by created pools. * @param maxIdle cap on the number of "sleeping" instances in the pool. */ public SoftReferencePoolFactory(PoolableObjectFactory factory, int maxIdle) { this(factory,maxIdle,SoftReferenceObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY); } /** * Create a new StackObjectPoolFactory. * * @param factory the PoolableObjectFactory used by created pools. * @param maxIdle cap on the number of "sleeping" instances in the pool. * @param initIdleCapacity - initial size of the pool (this specifies the size of the container, it does not cause the pool to be pre-populated.) */ public SoftReferencePoolFactory(PoolableObjectFactory factory, int maxIdle, int initIdleCapacity) { _factory = factory; _maxSleeping = maxIdle; _initCapacity = initIdleCapacity; } public ObjectPool createPool() { return new SoftReferenceObjectPool(_factory,_maxSleeping,_initCapacity); } protected PoolableObjectFactory _factory = null; protected int _maxSleeping = SoftReferenceObjectPool.DEFAULT_MAX_SLEEPING; protected int _initCapacity = SoftReferenceObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY; public void activateObject(Object obj) throws Exception { // TODO Auto-generated method stub } public void destroyObject(Object obj) throws Exception { // TODO Auto-generated method stub } public Object makeObject() throws Exception { // TODO Auto-generated method stub return null; } public void passivateObject(Object obj) throws Exception { // TODO Auto-generated method stub } public boolean validateObject(Object obj) { // TODO Auto-generated method stub return false; } }
附加实例: 另一人写的简单objectpool package com.thoughtworks.xstream.core.util; /** * A simple pool implementation. * * @author Jörg Schaible * @author Joe Walnes */ public class Pool { public interface Factory { public Object newInstance(); } private final int initialPoolSize; private final int maxPoolSize; private final Factory factory; private transient Object[] pool; private transient int nextAvailable; private transient Object mutex = new Object(); public Pool(int initialPoolSize, int maxPoolSize, Factory factory) { this.initialPoolSize = initialPoolSize; this.maxPoolSize = maxPoolSize; this.factory = factory; } public Object fetchFromPool() { Object result; synchronized (mutex) { if (pool == null) { pool = new Object[maxPoolSize]; for (nextAvailable = initialPoolSize; nextAvailable > 0; ) { putInPool(factory.newInstance()); } } while (nextAvailable == maxPoolSize) { try { mutex.wait(); } catch (InterruptedException e) { throw new RuntimeException("Interrupted whilst waiting " + "for a free item in the pool : " + e.getMessage()); } } result = pool[nextAvailable++]; if (result == null) { result = factory.newInstance(); putInPool(result); ++nextAvailable; } } return result; } protected void putInPool(Object object) { synchronized (mutex) { pool[--nextAvailable] = object; mutex.notify(); } } private Object readResolve() { mutex = new Object(); return this; } }
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
浏览 5668 次