如果一种类型的对象需要经常被创建、销毁,为了提高性能,我们通常需要使用“池”技术,就如线程池、TCP连接池等一样。那么需要使用池技术的对象一般有哪些特征了?
(1)创建过程耗时
(2)不需要保存客户状态
(3)对象体积较大
(4)频繁创建/销毁
为了省事,我希望实现一个万能对象池组件,该对象池可以缓存任意类型的对象。下面给出对象池的接口:
public interface IObjectPool
![](Images/ExpandedBlockStart.gif) {
//objType为缓存的对象的类型,cArgs为缓存对象的构造参数
bool Initialize(Type objType ,object[] cArgs ,int minNum ,int maxNum) ;
object RentObject() ;
void GiveBackObject(int objHashCode) ;
void Dispose() ;
![](Images/InBlock.gif)
![](Images/ExpandedSubBlockStart.gif) int MinObjCount {get ;}
![](Images/ExpandedSubBlockStart.gif) int MaxObjCount {get ;}
![](Images/ExpandedSubBlockStart.gif) int CurObjCount {get ;}
![](Images/ExpandedSubBlockStart.gif) int IdleObjCount {get ;}
![](Images/InBlock.gif)
event CallBackObjPool PoolShrinked ;
event CallBackObjPool MemoryUseOut ; //内存分配失败
}
![](Images/None.gif)
public delegate void CallBackObjPool() ;
上面接口中的各个方法的含义很清楚。其中PoolShrinked表示池中的对象个数有Max变为Min。
我们可以考虑这样一种情况,当我们需要缓存的对象需要维持和一个客户之间的状态,那么也是可以的,如果是这样,所缓存的类型最好实现下面的IPooledObjSupporter接口。
public interface IPooledObjSupporter : IDisposable
![](Images/ExpandedBlockStart.gif) {
void Reset() ; //恢复对象为初始状态,当IObjectPool.GiveBackObject时调用
}
对象在实现该接口后,就可以被对象池在收到归还的对象时重置其状态了。整个对象池的实现代码如下:
using System;
using System.Collections ;
using System.Reflection;
![](Images/None.gif)
namespace EnterpriseServerBase.Infrastructure
![](Images/ExpandedBlockStart.gif) ![](Images/ContractedBlock.gif) {
![](Images/ExpandedSubBlockStart.gif) /**//// <summary>
/// IObjectPool 的默认实现。
/// 作者:朱伟 sky.zhuwei@163.com
/// </summary>
![](Images/ExpandedSubBlockStart.gif) ObjectPool#region ObjectPool
public class ObjectPool :IObjectPool
![](Images/ExpandedSubBlockStart.gif) {
![](Images/ExpandedSubBlockStart.gif) members#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
![](Images/InBlock.gif)
![](Images/ExpandedSubBlockStart.gif) IObjectPool 成员#region IObjectPool 成员
public event CallBackObjPool PoolShrinked ;
public event CallBackObjPool MemoryUseOut ;
![](Images/InBlock.gif)
public bool Initialize(Type objType, object[] cArgs, int minNum, int maxNum)
![](Images/ExpandedSubBlockStart.gif) {
if(minNum < 1)
![](Images/ExpandedSubBlockStart.gif) {
minNum = 1 ;
}
if(maxNum < 5)
![](Images/ExpandedSubBlockStart.gif) {
maxNum = 5 ;
}
![](Images/InBlock.gif)
this.destType = objType ;
this.ctorArgs = cArgs ;
this.minObjCount = minNum ;
this.maxObjCount = maxNum ;
double cof = 1 - ((double)minNum /(double)maxNum) ;
this.shrinkPoint = (int)(cof * minNum) ;
![](Images/InBlock.gif)
//缓存的类型是否支持IPooledObjSupporter接口
Type supType = typeof(IPooledObjSupporter) ;
if(supType.IsAssignableFrom(objType))
![](Images/ExpandedSubBlockStart.gif) {
this.supportReset = true ;
}
![](Images/InBlock.gif)
this.InstanceObjects() ;
![](Images/InBlock.gif)
return true ;
}
![](Images/InBlock.gif)
private void InstanceObjects()
![](Images/ExpandedSubBlockStart.gif) {
for(int i=0 ;i<this.minObjCount ;i++)
![](Images/ExpandedSubBlockStart.gif) {
this.CreateOneObject() ;
}
}
![](Images/InBlock.gif)
![](Images/ExpandedSubBlockStart.gif) CreateOneObject ,DistroyOneObject#region CreateOneObject ,DistroyOneObject
private int CreateOneObject()
![](Images/ExpandedSubBlockStart.gif) {
object obj = null ;
![](Images/InBlock.gif)
try
![](Images/ExpandedSubBlockStart.gif) {
obj = Activator.CreateInstance(this.destType ,this.ctorArgs) ;
}
catch(Exception ee) //分配内存失败!
![](Images/ExpandedSubBlockStart.gif) {
ee = ee ;
this.maxObjCount = this.CurObjCount ;
if(this.minObjCount > this.CurObjCount)
![](Images/ExpandedSubBlockStart.gif) {
this.minObjCount = this.CurObjCount ;
}
![](Images/InBlock.gif)
if(this.MemoryUseOut != null)
![](Images/ExpandedSubBlockStart.gif) {
this.MemoryUseOut() ;
}
![](Images/InBlock.gif)
return -1 ;
}
![](Images/InBlock.gif)
int key = obj.GetHashCode() ;
this.hashTableObjs.Add(key ,obj) ;
this.hashTableStatus.Add(key ,true ) ;
this.keyList.Add(key) ;
![](Images/InBlock.gif)
return key ;
}
![](Images/InBlock.gif)
private void DistroyOneObject(int key)
![](Images/ExpandedSubBlockStart.gif) {
object target = this.hashTableObjs[key] ;
IDisposable tar = target as IDisposable ;
if(tar != null)
![](Images/ExpandedSubBlockStart.gif) {
tar.Dispose() ;
}
![](Images/InBlock.gif)
this.hashTableObjs.Remove(key) ;
this.hashTableStatus.Remove(key) ;
this.keyList.Remove(key) ;
}
#endregion
![](Images/InBlock.gif)
public object RentObject()
![](Images/ExpandedSubBlockStart.gif) {
lock(this)
![](Images/ExpandedSubBlockStart.gif) {
object target = null ;
foreach(int key in this.keyList)
![](Images/ExpandedSubBlockStart.gif) {
if((bool)this.hashTableStatus[key]) //isIdle
![](Images/ExpandedSubBlockStart.gif) {
this.hashTableStatus[key] = false ;
target = this.hashTableObjs[key] ;
break ;
}
}
![](Images/InBlock.gif)
if(target == null)
![](Images/ExpandedSubBlockStart.gif) {
if(this.keyList.Count < this.maxObjCount)
![](Images/ExpandedSubBlockStart.gif) {
int key = this.CreateOneObject() ;
if(key != -1)
![](Images/ExpandedSubBlockStart.gif) {
this.hashTableStatus[key] = false ;
target = this.hashTableObjs[key] ;
}
}
}
![](Images/InBlock.gif)
return target ;
}
}
![](Images/InBlock.gif)
![](Images/ExpandedSubBlockStart.gif) GiveBackObject#region GiveBackObject
public void GiveBackObject(int objHashCode)
![](Images/ExpandedSubBlockStart.gif) {
if(this.hashTableStatus[objHashCode] == null)
![](Images/ExpandedSubBlockStart.gif) {
return ;
}
![](Images/InBlock.gif)
lock(this)
![](Images/ExpandedSubBlockStart.gif) {
this.hashTableStatus[objHashCode] = true ;
if(this.supportReset)
![](Images/ExpandedSubBlockStart.gif) {
IPooledObjSupporter supporter = (IPooledObjSupporter)this.hashTableObjs[objHashCode] ;
supporter.Reset() ;
}
![](Images/InBlock.gif)
if(this.CanShrink())
![](Images/ExpandedSubBlockStart.gif) {
this.Shrink() ;
}
}
}
![](Images/InBlock.gif)
//能够收缩对象池
private bool CanShrink()
![](Images/ExpandedSubBlockStart.gif) {
int idleCount = this.GetIdleObjCount() ;
int busyCount = this.CurObjCount - idleCount ;
![](Images/InBlock.gif)
return (busyCount < this.shrinkPoint) && (this.CurObjCount > (this.minObjCount + (this.maxObjCount - this.minObjCount)/2)) ;
}
private void Shrink()
![](Images/ExpandedSubBlockStart.gif) {
while(this.CurObjCount > this.minObjCount)
![](Images/ExpandedSubBlockStart.gif) {
int destKey = -1 ;
foreach(int key in this.keyList)
![](Images/ExpandedSubBlockStart.gif) {
if((bool)this.hashTableStatus[key])
![](Images/ExpandedSubBlockStart.gif) {
destKey = key ;
break ;
}
}
![](Images/InBlock.gif)
if(destKey != -1)
![](Images/ExpandedSubBlockStart.gif) {
this.DistroyOneObject(destKey) ;
}
else
![](Images/ExpandedSubBlockStart.gif) {
break ;
}
}
![](Images/InBlock.gif)
if(this.PoolShrinked != null)
![](Images/ExpandedSubBlockStart.gif) {
this.PoolShrinked() ;
}
}
#endregion
![](Images/InBlock.gif)
public void Dispose()
![](Images/ExpandedSubBlockStart.gif) {
Type supType = typeof(System.IDisposable) ;
if(supType.IsAssignableFrom(this.destType))
![](Images/ExpandedSubBlockStart.gif) {
ArrayList list = (ArrayList)this.keyList.Clone() ;
foreach(int key in list)
![](Images/ExpandedSubBlockStart.gif) {
this.DistroyOneObject(key) ;
}
}
![](Images/InBlock.gif)
this.hashTableStatus.Clear() ;
this.hashTableObjs.Clear() ;
this.keyList.Clear() ;
}
![](Images/InBlock.gif)
![](Images/ExpandedSubBlockStart.gif) property#region property
public int MinObjCount
![](Images/ExpandedSubBlockStart.gif) {
get
![](Images/ExpandedSubBlockStart.gif) {
return this.minObjCount ;
}
}
![](Images/InBlock.gif)
public int MaxObjCount
![](Images/ExpandedSubBlockStart.gif) {
get
![](Images/ExpandedSubBlockStart.gif) {
return this.maxObjCount ;
}
}
![](Images/InBlock.gif)
public int CurObjCount
![](Images/ExpandedSubBlockStart.gif) {
get
![](Images/ExpandedSubBlockStart.gif) {
return this.keyList.Count ;
}
}
![](Images/InBlock.gif)
public int IdleObjCount
![](Images/ExpandedSubBlockStart.gif) {
get
![](Images/ExpandedSubBlockStart.gif) {
lock(this)
![](Images/ExpandedSubBlockStart.gif) {
return this.GetIdleObjCount() ;
}
}
}
![](Images/InBlock.gif)
private int GetIdleObjCount()
![](Images/ExpandedSubBlockStart.gif) {
int count = 0 ;
foreach(int key in this.keyList)
![](Images/ExpandedSubBlockStart.gif) {
if((bool)this.hashTableStatus[key])
![](Images/ExpandedSubBlockStart.gif) {
++ count ;
}
}
![](Images/InBlock.gif)
return count ;
}
#endregion
![](Images/InBlock.gif)
#endregion
}
#endregion
}
对象在实现该接口后,就可以被对象池在收到归还的对象时重置其状态了。整个对象池的实现代码如下:
using System;
using System.Collections ;
using System.Reflection;
![](Images/None.gif)
namespace EnterpriseServerBase.Infrastructure
![](Images/ExpandedBlockStart.gif) ![](Images/ContractedBlock.gif) {
![](Images/ExpandedSubBlockStart.gif) /**//// <summary>
/// IObjectPool 的默认实现。
/// 作者:朱伟 sky.zhuwei@163.com
/// </summary>
![](Images/ExpandedSubBlockStart.gif) ObjectPool#region ObjectPool
public class ObjectPool :IObjectPool
![](Images/ExpandedSubBlockStart.gif) {
![](Images/ExpandedSubBlockStart.gif) members#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
![](Images/InBlock.gif)
![](Images/ExpandedSubBlockStart.gif) IObjectPool 成员#region IObjectPool 成员
public event CallBackObjPool PoolShrinked ;
public event CallBackObjPool MemoryUseOut ;
![](Images/InBlock.gif)
public bool Initialize(Type objType, object[] cArgs, int minNum, int maxNum)
![](Images/ExpandedSubBlockStart.gif) {
if(minNum < 1)
![](Images/ExpandedSubBlockStart.gif) {
minNum = 1 ;
}
if(maxNum < 5)
![](Images/ExpandedSubBlockStart.gif) {
maxNum = 5 ;
}
![](Images/InBlock.gif)
this.destType = objType ;
this.ctorArgs = cArgs ;
this.minObjCount = minNum ;
this.maxObjCount = maxNum ;
double cof = 1 - ((double)minNum /(double)maxNum) ;
this.shrinkPoint = (int)(cof * minNum) ;
![](Images/InBlock.gif)
//缓存的类型是否支持IPooledObjSupporter接口
Type supType = typeof(IPooledObjSupporter) ;
if(supType.IsAssignableFrom(objType))
![](Images/ExpandedSubBlockStart.gif) {
this.supportReset = true ;
}
![](Images/InBlock.gif)
this.InstanceObjects() ;
![](Images/InBlock.gif)
return true ;
}
![](Images/InBlock.gif)
private void InstanceObjects()
![](Images/ExpandedSubBlockStart.gif) {
for(int i=0 ;i<this.minObjCount ;i++)
![](Images/ExpandedSubBlockStart.gif) {
this.CreateOneObject() ;
}
}
![](Images/InBlock.gif)
![](Images/ExpandedSubBlockStart.gif) CreateOneObject ,DistroyOneObject#region CreateOneObject ,DistroyOneObject
private int CreateOneObject()
![](Images/ExpandedSubBlockStart.gif) {
object obj = null ;
![](Images/InBlock.gif)
try
![](Images/ExpandedSubBlockStart.gif) {
obj = Activator.CreateInstance(this.destType ,this.ctorArgs) ;
}
catch(Exception ee) //分配内存失败!
![](Images/ExpandedSubBlockStart.gif) {
ee = ee ;
this.maxObjCount = this.CurObjCount ;
if(this.minObjCount > this.CurObjCount)
![](Images/ExpandedSubBlockStart.gif) {
this.minObjCount = this.CurObjCount ;
}
![](Images/InBlock.gif)
if(this.MemoryUseOut != null)
![](Images/ExpandedSubBlockStart.gif) {
this.MemoryUseOut() ;
}
![](Images/InBlock.gif)
return -1 ;
}
![](Images/InBlock.gif)
int key = obj.GetHashCode() ;
this.hashTableObjs.Add(key ,obj) ;
this.hashTableStatus.Add(key ,true ) ;
this.keyList.Add(key) ;
![](Images/InBlock.gif)
return key ;
}
![](Images/InBlock.gif)
private void DistroyOneObject(int key)
![](Images/ExpandedSubBlockStart.gif) {
object target = this.hashTableObjs[key] ;
IDisposable tar = target as IDisposable ;
if(tar != null)
![](Images/ExpandedSubBlockStart.gif) {
tar.Dispose() ;
}
![](Images/InBlock.gif)
this.hashTableObjs.Remove(key) ;
this.hashTableStatus.Remove(key) ;
this.keyList.Remove(key) ;
}
#endregion
![](Images/InBlock.gif)
public object RentObject()
![](Images/ExpandedSubBlockStart.gif) {
lock(this)
![](Images/ExpandedSubBlockStart.gif) {
object target = null ;
foreach(int key in this.keyList)
![](Images/ExpandedSubBlockStart.gif) {
if((bool)this.hashTableStatus[key]) //isIdle
![](Images/ExpandedSubBlockStart.gif) {
this.hashTableStatus[key] = false ;
target = this.hashTableObjs[key] ;
break ;
}
}
![](Images/InBlock.gif)
if(target == null)
![](Images/ExpandedSubBlockStart.gif) {
if(this.keyList.Count < this.maxObjCount)
![](Images/ExpandedSubBlockStart.gif) {
int key = this.CreateOneObject() ;
if(key != -1)
![](Images/ExpandedSubBlockStart.gif) {
this.hashTableStatus[key] = false ;
target = this.hashTableObjs[key] ;
}
}
}
![](Images/InBlock.gif)
return target ;
}
}
![](Images/InBlock.gif)
![](Images/ExpandedSubBlockStart.gif) GiveBackObject#region GiveBackObject
public void GiveBackObject(int objHashCode)
![](Images/ExpandedSubBlockStart.gif) {
if(this.hashTableStatus[objHashCode] == null)
![](Images/ExpandedSubBlockStart.gif) {
return ;
}
![](Images/InBlock.gif)
lock(this)
![](Images/ExpandedSubBlockStart.gif) {
this.hashTableStatus[objHashCode] = true ;
if(this.supportReset)
![](Images/ExpandedSubBlockStart.gif) {
IPooledObjSupporter supporter = (IPooledObjSupporter)this.hashTableObjs[objHashCode] ;
supporter.Reset() ;
}
![](Images/InBlock.gif)
if(this.CanShrink())
![](Images/ExpandedSubBlockStart.gif) {
this.Shrink() ;
}
}
}
![](Images/InBlock.gif)
//能够收缩对象池
private bool CanShrink()
![](Images/ExpandedSubBlockStart.gif) {
int idleCount = this.GetIdleObjCount() ;
int busyCount = this.CurObjCount - idleCount ;
![](Images/InBlock.gif)
return (busyCount < this.shrinkPoint) && (this.CurObjCount > (this.minObjCount + (this.maxObjCount - this.minObjCount)/2)) ;
}
private void Shrink()
![](Images/ExpandedSubBlockStart.gif) {
while(this.CurObjCount > this.minObjCount)
![](Images/ExpandedSubBlockStart.gif) {
int destKey = -1 ;
foreach(int key in this.keyList)
![](Images/ExpandedSubBlockStart.gif) {
if((bool)this.hashTableStatus[key])
![](Images/ExpandedSubBlockStart.gif) {
destKey = key ;
break ;
}
}
![](Images/InBlock.gif)
if(destKey != -1)
![](Images/ExpandedSubBlockStart.gif) {
this.DistroyOneObject(destKey) ;
}
else
![](Images/ExpandedSubBlockStart.gif) {
break ;
}
}
![](Images/InBlock.gif)
if(this.PoolShrinked != null)
![](Images/ExpandedSubBlockStart.gif) {
this.PoolShrinked() ;
}
}
#endregion
![](Images/InBlock.gif)
public void Dispose()
![](Images/ExpandedSubBlockStart.gif) {
Type supType = typeof(System.IDisposable) ;
if(supType.IsAssignableFrom(this.destType))
![](Images/ExpandedSubBlockStart.gif) {
ArrayList list = (ArrayList)this.keyList.Clone() ;
foreach(int key in list)
![](Images/ExpandedSubBlockStart.gif) {
this.DistroyOneObject(key) ;
}
}
![](Images/InBlock.gif)
this.hashTableStatus.Clear() ;
this.hashTableObjs.Clear() ;
this.keyList.Clear() ;
}
![](Images/InBlock.gif)
![](Images/ExpandedSubBlockStart.gif) property#region property
public int MinObjCount
![](Images/ExpandedSubBlockStart.gif) {
get
![](Images/ExpandedSubBlockStart.gif) {
return this.minObjCount ;
}
}
![](Images/InBlock.gif)
public int MaxObjCount
![](Images/ExpandedSubBlockStart.gif) {
get
![](Images/ExpandedSubBlockStart.gif) {
return this.maxObjCount ;
}
}
![](Images/InBlock.gif)
public int CurObjCount
![](Images/ExpandedSubBlockStart.gif) {
get
![](Images/ExpandedSubBlockStart.gif) {
return this.keyList.Count ;
}
}
![](Images/InBlock.gif)
public int IdleObjCount
![](Images/ExpandedSubBlockStart.gif) {
get
![](Images/ExpandedSubBlockStart.gif) {
lock(this)
![](Images/ExpandedSubBlockStart.gif) {
return this.GetIdleObjCount() ;
}
}
}
![](Images/InBlock.gif)
private int GetIdleObjCount()
![](Images/ExpandedSubBlockStart.gif) {
int count = 0 ;
foreach(int key in this.keyList)
![](Images/ExpandedSubBlockStart.gif) {
if((bool)this.hashTableStatus[key])
![](Images/ExpandedSubBlockStart.gif) {
++ count ;
}
}
![](Images/InBlock.gif)
return count ;
}
#endregion
![](Images/InBlock.gif)
#endregion
}
#endregion
}
|