如果一种类型的对象需要经常被创建、销毁,为了提高性能,我们通常需要使用“池”技术,就如线程池、TCP连接池等一样。那么需要使用池技术的对象一般有哪些特征了?
( 1)创建过程耗时
( 2)不需要保存客户状态
( 3)对象体积较大
( 4)频繁创建/销毁
为了省事,我希望实现一个万能对象池组件,该对象池可以缓存任意类型的对象。下面给出对象池的接口:
public
interface
IObjectPool
{
// objType为缓存的对象的类型,cArgs为缓存对象的构造参数
bool Initialize(TypeobjType, 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 CallBackObjPoolPoolShrinked;
event CallBackObjPoolMemoryUseOut; // 内存分配失败
}
public delegate void CallBackObjPool();
{
// objType为缓存的对象的类型,cArgs为缓存对象的构造参数
bool Initialize(TypeobjType, 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 CallBackObjPoolPoolShrinked;
event CallBackObjPoolMemoryUseOut; // 内存分配失败
}
public delegate void CallBackObjPool();
上面接口中的各个方法的含义很清楚。其中PoolShrinked表示池中的对象个数有Max变为Min。
我们可以考虑这样一种情况,当我们需要缓存的对象需要维持和一个客户之间的状态,那么也是可以的,如果是这样,所缓存的类型最好实现下面的
IPooledObjSupporter
接口。
public
interface
IPooledObjSupporter:IDisposable
{
void Reset(); // 恢复对象为初始状态,当IObjectPool.GiveBackObject时调用
}
{
void Reset(); // 恢复对象为初始状态,当IObjectPool.GiveBackObject时调用
}
对象在实现该接口后,就可以被对象池在收到归还的对象时重置其状态了。整个对象池的实现代码如下:
using
System;
using System.Collections;
using System.Reflection;
namespace EnterpriseServerBase.Infrastructure
{
/// <summary>
/// IObjectPool的默认实现。
/// 作者:朱伟sky.zhuwei@163.com
/// </summary>
#region ObjectPool
public class ObjectPool:IObjectPool
{
#region members
private TypedestType = null ;
private object []ctorArgs = null ;
private int minObjCount = 0 ;
private int maxObjCount = 0 ;
private int shrinkPoint = 0 ;
private HashtablehashTableObjs = new Hashtable();
private HashtablehashTableStatus = new Hashtable(); // key-isIdle其中key就是hashcode
private ArrayListkeyList = new ArrayList();
private bool supportReset = false ;
#endregion
#region IObjectPool成员
public event CallBackObjPoolPoolShrinked;
public event CallBackObjPoolMemoryUseOut;
public bool Initialize(TypeobjType, 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接口
TypesupType = 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();
}
}
#region CreateOneObject,DistroyOneObject
private int CreateOneObject()
{
object obj = null ;
try
{
obj = Activator.CreateInstance( this .destType, this .ctorArgs);
}
catch (Exceptionee) // 分配内存失败!
{
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];
IDisposabletar = 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)
{
IPooledObjSupportersupporter = (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()
{
TypesupType = typeof (System.IDisposable);
if (supType.IsAssignableFrom( this .destType))
{
ArrayListlist = (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
}
using System.Collections;
using System.Reflection;
namespace EnterpriseServerBase.Infrastructure
{
/// <summary>
/// IObjectPool的默认实现。
/// 作者:朱伟sky.zhuwei@163.com
/// </summary>
#region ObjectPool
public class ObjectPool:IObjectPool
{
#region members
private TypedestType = null ;
private object []ctorArgs = null ;
private int minObjCount = 0 ;
private int maxObjCount = 0 ;
private int shrinkPoint = 0 ;
private HashtablehashTableObjs = new Hashtable();
private HashtablehashTableStatus = new Hashtable(); // key-isIdle其中key就是hashcode
private ArrayListkeyList = new ArrayList();
private bool supportReset = false ;
#endregion
#region IObjectPool成员
public event CallBackObjPoolPoolShrinked;
public event CallBackObjPoolMemoryUseOut;
public bool Initialize(TypeobjType, 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接口
TypesupType = 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();
}
}
#region CreateOneObject,DistroyOneObject
private int CreateOneObject()
{
object obj = null ;
try
{
obj = Activator.CreateInstance( this .destType, this .ctorArgs);
}
catch (Exceptionee) // 分配内存失败!
{
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];
IDisposabletar = 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)
{
IPooledObjSupportersupporter = (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()
{
TypesupType = typeof (System.IDisposable);
if (supType.IsAssignableFrom( this .destType))
{
ArrayListlist = (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时调用
}
{
void Reset(); // 恢复对象为初始状态,当IObjectPool.GiveBackObject时调用
}
对象在实现该接口后,就可以被对象池在收到归还的对象时重置其状态了。整个对象池的实现代码如下:
using
System;
using System.Collections;
using System.Reflection;
namespace EnterpriseServerBase.Infrastructure
{
/// <summary>
/// IObjectPool的默认实现。
/// 作者:朱伟sky.zhuwei@163.com
/// </summary>
#region ObjectPool
public class ObjectPool:IObjectPool
{
#region members
private TypedestType = null ;
private object []ctorArgs = null ;
private int minObjCount = 0 ;
private int maxObjCount = 0 ;
private int shrinkPoint = 0 ;
private HashtablehashTableObjs = new Hashtable();
private HashtablehashTableStatus = new Hashtable(); // key-isIdle其中key就是hashcode
private ArrayListkeyList = new ArrayList();
private bool supportReset = false ;
#endregion
#region IObjectPool成员
public event CallBackObjPoolPoolShrinked;
public event CallBackObjPoolMemoryUseOut;
public bool Initialize(TypeobjType, 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接口
TypesupType = 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();
}
}
#region CreateOneObject,DistroyOneObject
private int CreateOneObject()
{
object obj = null ;
try
{
obj = Activator.CreateInstance( this .destType, this .ctorArgs);
}
catch (Exceptionee) // 分配内存失败!
{
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];
IDisposabletar = 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)
{
IPooledObjSupportersupporter = (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()
{
TypesupType = typeof (System.IDisposable);
if (supType.IsAssignableFrom( this .destType))
{
ArrayListlist = (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
}
using System.Collections;
using System.Reflection;
namespace EnterpriseServerBase.Infrastructure
{
/// <summary>
/// IObjectPool的默认实现。
/// 作者:朱伟sky.zhuwei@163.com
/// </summary>
#region ObjectPool
public class ObjectPool:IObjectPool
{
#region members
private TypedestType = null ;
private object []ctorArgs = null ;
private int minObjCount = 0 ;
private int maxObjCount = 0 ;
private int shrinkPoint = 0 ;
private HashtablehashTableObjs = new Hashtable();
private HashtablehashTableStatus = new Hashtable(); // key-isIdle其中key就是hashcode
private ArrayListkeyList = new ArrayList();
private bool supportReset = false ;
#endregion
#region IObjectPool成员
public event CallBackObjPoolPoolShrinked;
public event CallBackObjPoolMemoryUseOut;
public bool Initialize(TypeobjType, 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接口
TypesupType = 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();
}
}
#region CreateOneObject,DistroyOneObject
private int CreateOneObject()
{
object obj = null ;
try
{
obj = Activator.CreateInstance( this .destType, this .ctorArgs);
}
catch (Exceptionee) // 分配内存失败!
{
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];
IDisposabletar = 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)
{
IPooledObjSupportersupporter = (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()
{
TypesupType = typeof (System.IDisposable);
if (supType.IsAssignableFrom( this .destType))
{
ArrayListlist = (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
}