如果一种类型的对象需要经常被创建、销毁,为了提高性能,我们通常需要使用“池”技术,就如线程池、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
{
/**//// <summary>
/// IObjectPool 的默认实现。
/// 作者:朱伟 sky.zhuwei@163.com
/// </summary>
ObjectPool#region ObjectPool
public class ObjectPool :IObjectPool
{
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
IObjectPool 成员#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.minObjCount ;i++)
{
this.CreateOneObject() ;
}
}
CreateOneObject ,DistroyOneObject#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 ;
}
}
GiveBackObject#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() ;
}
property#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
}
对象在实现该接口后,就可以被对象池在收到归还的对象时重置其状态了。整个对象池的实现代码如下:
using System;
using System.Collections ;
using System.Reflection;
namespace EnterpriseServerBase.Infrastructure
{
/**//// <summary>
/// IObjectPool 的默认实现。
/// 作者:朱伟 sky.zhuwei@163.com
/// </summary>
ObjectPool#region ObjectPool
public class ObjectPool :IObjectPool
{
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
IObjectPool 成员#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.minObjCount ;i++)
{
this.CreateOneObject() ;
}
}
CreateOneObject ,DistroyOneObject#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 ;
}
}
GiveBackObject#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() ;
}
property#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
}
|