万能对象池【C#实现】

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

上面接口中的各个方法的含义很清楚。其中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 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


IObjectPool成员 #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();
}

}


CreateOneObject,DistroyOneObject #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;
}


}


GiveBackObject #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();
}


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

}

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 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


IObjectPool成员 #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();
}

}


CreateOneObject,DistroyOneObject #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;
}


}


GiveBackObject #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();
}


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

}

万能对象池【C#实现】


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论