如果一种类型的对象需要经常被创建、销毁,为了提高性能,我们通常需要使用“池”技术,就如线程池、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
}
|