如果一种类型的对象需要经常被创建、销毁,为了提高性能,我们通常需要使用“池”技术,就如线程池、TCP
连接池等一样。那么需要使用池技术的对象一般有哪些特征了?
(1)创建过程耗时

(2)不需要保存客户状态

(3)对象体积较大

(4)频繁创建/销毁

为了省事,我希望实现一个万能对象池组件,该对象池可以缓存任意类型的对象。下面给出对象池的接

口:

public interface IObjectPool
{
//objType为缓存的对象的类型,cArgs为缓存对象的构造参数
bool Initialize(Type objType ,object[] cArgs ,int minNum ,int maxNum) ;
object RentObject() ;
void GiveBackObject(int objHashCode) ;
void Dispose() ;

int MinObjCount {get ;}
int MaxObjCount {get ;}
int CurObjCount {get ;}
int IdleObjCount {get ;}

event CallBackObjPool PoolShrinked ;
event CallBackObjPool MemoryUseOut ; //内存分配失败
}

public delegate void CallBackObjPool() ;
上面接口中的各个方法的含义很清楚。其中PoolShrinked表示池中的对象个数有Max变为Min。

我们可以考虑这样一种情况,当我们需要缓存的对象需要维持和一个客户之间的状态,那么也是可以的,如果是

这样,所缓存的类型最好实现下面的IPooledObjSupporter接口。


public interface IPooledObjSupporter : IDisposable
{
void Reset() ; //恢复对象为初始状态,当IObjectPool.GiveBackObject时调用
}
对象在实现该接口后,就可以被对象池在收到归还的对象时重置其状态了。整个对象池的实现代码如

下:

using System;
using System.Collections ;
using System.Reflection;

namespace EnterpriseServerBase.Infrastructure
{
///
/// IObjectPool 的默认实现。
/// 作者:吴志豪 wzh1988@gmail.com
///

#region ObjectPool
public class ObjectPool :IObjectPool
{
#region members
private Type destType = null ;
private object[] ctorArgs = null ;
private int minObjCount = 0 ;
private int maxObjCount = 0 ;
private int shrinkPoint = 0 ;
private Hashtable hashTableObjs = new Hashtable() ;
private Hashtable hashTableStatus = new Hashtable() ; //key - isIdle 其中key就是

hashcode
private ArrayList keyList = new ArrayList() ;
private bool supportReset = false ;
#endregion

#region IObjectPool 成员
public event CallBackObjPool PoolShrinked ;
public event CallBackObjPool MemoryUseOut ;

public bool Initialize(Type objType, object[] cArgs, int minNum, int maxNum)
{
if(minNum < 1)
{
minNum = 1 ;
}
if(maxNum < 5)
{
maxNum = 5 ;
}

this.destType = objType ;
this.ctorArgs = cArgs ;
this.minObjCount = minNum ;
this.maxObjCount = maxNum ;
double cof = 1 - ((double)minNum /(double)maxNum) ;
this.shrinkPoint = (int)(cof * minNum) ;

//缓存的类型是否支持IPooledObjSupporter接口
Type supType = typeof(IPooledObjSupporter) ;
if(supType.IsAssignableFrom(objType))
{
this.supportReset = true ;
}

this.InstanceObjects() ;

return true ;
}

private void InstanceObjects()
{
for(int i=0 ;i {
this.CreateOneObject() ;
}
}

#region CreateOneObject ,DistroyOneObject
private int CreateOneObject()
{
object obj = null ;

try
{
obj = Activator.CreateInstance(this.destType ,this.ctorArgs) ;
}
catch(Exception ee) //分配内存失败!
{
ee = ee ;
this.maxObjCount = this.CurObjCount ;
if(this.minObjCount > this.CurObjCount)
{
this.minObjCount = this.CurObjCount ;
}

if(this.MemoryUseOut != null)
{
this.MemoryUseOut() ;
}

return -1 ;
}

int key = obj.GetHashCode() ;
this.hashTableObjs.Add(key ,obj) ;
this.hashTableStatus.Add(key ,true ) ;
this.keyList.Add(key) ;

return key ;
}

private void DistroyOneObject(int key)
{
object target = this.hashTableObjs[key] ;
IDisposable tar = target as IDisposable ;
if(tar != null)
{
tar.Dispose() ;
}

this.hashTableObjs.Remove(key) ;
this.hashTableStatus.Remove(key) ;
this.keyList.Remove(key) ;
}
#endregion

public object RentObject()
{
lock(this)
{
object target = null ;
foreach(int key in this.keyList)
{
if((bool)this.hashTableStatus[key]) //isIdle
{
this.hashTableStatus[key] = false ;
target = this.hashTableObjs[key] ;
break ;
}
}

if(target == null)
{
if(this.keyList.Count < this.maxObjCount)
{
int key = this.CreateOneObject() ;
if(key != -1)
{
this.hashTableStatus[key] = false ;
target = this.hashTableObjs[key] ;
}
}
}

return target ;
}

}

#region GiveBackObject
public void GiveBackObject(int objHashCode)
{
if(this.hashTableStatus[objHashCode] == null)
{
return ;
}

lock(this)
{
this.hashTableStatus[objHashCode] = true ;
if(this.supportReset)
{
IPooledObjSupporter supporter = (IPooledObjSupporter)this.hashTableObjs

[objHashCode] ;
supporter.Reset() ;
}

if(this.CanShrink())
{
this.Shrink() ;
}
}
}

//能够收缩对象池
private bool CanShrink()
{
int idleCount = this.GetIdleObjCount() ;
int busyCount = this.CurObjCount - idleCount ;

return (busyCount < this.shrinkPoint) && (this.CurObjCount > (this.minObjCount +

(this.maxObjCount - this.minObjCount)/2)) ;
}

private void Shrink()
{
while(this.CurObjCount > this.minObjCount)
{
int destKey = -1 ;
foreach(int key in this.keyList)
{
if((bool)this.hashTableStatus[key])
{
destKey = key ;
break ;
}
}

if(destKey != -1)
{
this.DistroyOneObject(destKey) ;
}
else
{
break ;
}
}

if(this.PoolShrinked != null)
{
this.PoolShrinked() ;
}
}
#endregion

public void Dispose()
{
Type supType = typeof(System.IDisposable) ;
if(supType.IsAssignableFrom(this.destType))
{
ArrayList list = (ArrayList)this.keyList.Clone() ;
foreach(int key in list)
{
this.DistroyOneObject(key) ;
}
}

this.hashTableStatus.Clear() ;
this.hashTableObjs.Clear() ;
this.keyList.Clear() ;
}

#region property
public int MinObjCount
{
get
{
return this.minObjCount ;
}
}

public int MaxObjCount
{
get
{
return this.maxObjCount ;
}
}

public int CurObjCount
{
get
{
return this.keyList.Count ;
}
}

public int IdleObjCount
{
get
{
lock(this)
{
return this.GetIdleObjCount() ;
}
}
}

private int GetIdleObjCount()
{
int count = 0 ;
foreach(int key in this.keyList)
{
if((bool)this.hashTableStatus[key])
{
++ count ;
}
}

return count ;
}
#endregion

#endregion
}
#endregion
}
public interface IPooledObjSupporter : IDisposable
{
void Reset() ; //恢复对象为初始状态,当IObjectPool.GiveBackObject时调用
}
对象在实现该接口后,就可以被对象池在收到归还的对象时重置其状态了。整个对象池的实现代码如

下:

using System;
using System.Collections ;
using System.Reflection;

namespace EnterpriseServerBase.Infrastructure
{
///
/// IObjectPool 的默认实现。
/// 作者:吴志豪 sky.zhuwei@163.com
///

#region ObjectPool
public class ObjectPool :IObjectPool
{
#region members
private Type destType = null ;
private object[] ctorArgs = null ;
private int minObjCount = 0 ;
private int maxObjCount = 0 ;
private int shrinkPoint = 0 ;
private Hashtable hashTableObjs = new Hashtable() ;
private Hashtable hashTableStatus = new Hashtable() ; //key - isIdle 其中key就是

hashcode
private ArrayList keyList = new ArrayList() ;
private bool supportReset = false ;
#endregion

#region IObjectPool 成员
public event CallBackObjPool PoolShrinked ;
public event CallBackObjPool MemoryUseOut ;

public bool Initialize(Type objType, object[] cArgs, int minNum, int maxNum)
{
if(minNum < 1)
{
minNum = 1 ;
}
if(maxNum < 5)
{
maxNum = 5 ;
}

this.destType = objType ;
this.ctorArgs = cArgs ;
this.minObjCount = minNum ;
this.maxObjCount = maxNum ;
double cof = 1 - ((double)minNum /(double)maxNum) ;
this.shrinkPoint = (int)(cof * minNum) ;

//缓存的类型是否支持IPooledObjSupporter接口
Type supType = typeof(IPooledObjSupporter) ;
if(supType.IsAssignableFrom(objType))
{
this.supportReset = true ;
}

this.InstanceObjects() ;

return true ;
}

private void InstanceObjects()
{
for(int i=0 ;i {
this.CreateOneObject() ;
}
}

#region CreateOneObject ,DistroyOneObject
private int CreateOneObject()
{
object obj = null ;

try
{
obj = Activator.CreateInstance(this.destType ,this.ctorArgs) ;
}
catch(Exception ee) //分配内存失败!
{
ee = ee ;
this.maxObjCount = this.CurObjCount ;
if(this.minObjCount > this.CurObjCount)
{
this.minObjCount = this.CurObjCount ;
}

if(this.MemoryUseOut != null)
{
this.MemoryUseOut() ;
}

return -1 ;
}

int key = obj.GetHashCode() ;
this.hashTableObjs.Add(key ,obj) ;
this.hashTableStatus.Add(key ,true ) ;
this.keyList.Add(key) ;

return key ;
}

private void DistroyOneObject(int key)
{
object target = this.hashTableObjs[key] ;
IDisposable tar = target as IDisposable ;
if(tar != null)
{
tar.Dispose() ;
}

this.hashTableObjs.Remove(key) ;
this.hashTableStatus.Remove(key) ;
this.keyList.Remove(key) ;
}
#endregion

public object RentObject()
{
lock(this)
{
object target = null ;
foreach(int key in this.keyList)
{
if((bool)this.hashTableStatus[key]) //isIdle
{
this.hashTableStatus[key] = false ;
target = this.hashTableObjs[key] ;
break ;
}
}

if(target == null)
{
if(this.keyList.Count < this.maxObjCount)
{
int key = this.CreateOneObject() ;
if(key != -1)
{
this.hashTableStatus[key] = false ;
target = this.hashTableObjs[key] ;
}
}
}

return target ;
}

}

#region GiveBackObject
public void GiveBackObject(int objHashCode)
{
if(this.hashTableStatus[objHashCode] == null)
{
return ;
}

lock(this)
{
this.hashTableStatus[objHashCode] = true ;
if(this.supportReset)
{
IPooledObjSupporter supporter = (IPooledObjSupporter)this.hashTableObjs

[objHashCode] ;
supporter.Reset() ;
}

if(this.CanShrink())
{
this.Shrink() ;
}
}
}

//能够收缩对象池
private bool CanShrink()
{
int idleCount = this.GetIdleObjCount() ;
int busyCount = this.CurObjCount - idleCount ;

return (busyCount < this.shrinkPoint) && (this.CurObjCount > (this.minObjCount +

(this.maxObjCount - this.minObjCount)/2)) ;
}

private void Shrink()
{
while(this.CurObjCount > this.minObjCount)
{
int destKey = -1 ;
foreach(int key in this.keyList)
{
if((bool)this.hashTableStatus[key])
{
destKey = key ;
break ;
}
}

if(destKey != -1)
{
this.DistroyOneObject(destKey) ;
}
else
{
break ;
}
}

if(this.PoolShrinked != null)
{
this.PoolShrinked() ;
}
}
#endregion

public void Dispose()
{
Type supType = typeof(System.IDisposable) ;
if(supType.IsAssignableFrom(this.destType))
{
ArrayList list = (ArrayList)this.keyList.Clone() ;
foreach(int key in list)
{
this.DistroyOneObject(key) ;
}
}

this.hashTableStatus.Clear() ;
this.hashTableObjs.Clear() ;
this.keyList.Clear() ;
}

#region property
public int MinObjCount
{
get
{
return this.minObjCount ;
}
}

public int MaxObjCount
{
get
{
return this.maxObjCount ;
}
}

public int CurObjCount
{
get
{
return this.keyList.Count ;
}
}

public int IdleObjCount
{
get
{
lock(this)
{
return this.GetIdleObjCount() ;
}
}
}

private int GetIdleObjCount()
{
int count = 0 ;
foreach(int key in this.keyList)
{
if((bool)this.hashTableStatus[key])
{
++ count ;
}
}

return count ;
}
#endregion

#endregion
}
#endregion
}