@Author: cjcj cj.yangjun@gmail.com <c-j.iteye.com>
对象池(对Apache Commons部分源码分析)
2,如果pool的_maxSleeping阀值设置不当的话,在多线程APP下确实会导致堵塞...上限阀值和下限阀值很重要吧...
3,另外commons提供了一个ReferenceObjectPool,这种的好处在于内存不足时,GC无条件回收pool中的空闲对象,.这样资源可适当得到利用..不过pool中总要有一定量的闲对象,不可能每次都new吧。
4,commons中,是borrow()时,如果pool中没有空闲obj的时候,就创建新的obj,当然这个新对象是无状态的,所以建立在pool存储也需要建立在"无状态对象"的基本之上...
什么时候不要池化?
1#类似Point这样的轻量级对象,进行池化处理后,性能反而下降.
2#类似Point这样的轻量级对象,进行池化处理后,性能反而下降.
3#类似JPanel\Connection这样的重量级对象,进行池化处理后,性能有所上升,可以考虑池化。
Commons的几个功能方面:
1,pool的每个进出object都进行类型检查
2,提供了一个线程安全的版本.
3,对当前active object和sleeping object的控制
4,对object的获取和释放的时间控制
5,容错处理
设计结构:
2,ObjectPool用于管理要被池化的对象的借出和归还,并通知PoolableObjectFactory完成相应的工作;
设计重点:
1,池用某个容器存储对象(如Stack,List等)。
2,池中的每个对象是“干净”对象,或者说每一个从池中读取的对象都是一样初始化的对象(可取个别名为“裸对象”)。
3,对象-->裸对象 由外围的Factory来处理。
4,接口方式为:ObjectPool --> BaseObjectPool -->StackObjectPool
接口设计代码(对原设计有做简化):
以下是CommonsPool的接口,也就是最抽象的一层;
1、ObjectPool.java(pool的基本接口)
2、PoolableObjectFactory.java(Factory的基本接口)
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;
}
}
本文详细解析了Apache Commons Pool中的对象池设计原理及其实现细节,包括StackObjectPool和ReferenceObjectPool等。探讨了对象池的适用场景及其设计重点,同时提供了具体的接口设计和实现代码。
936

被折叠的 条评论
为什么被折叠?



