.NET 并行库写的对象池
基于.NET 并行库写的对象池
ObjectPoolBase类,大家不用去于解TObjectPool, TObjectPoolDomain, TObjectDomain三个泛型参数,改成一个TObject也可以使用
其构造中的四个参数分别代表:
minSize:池中最少个数
maxSize:池中最大个数
growSize:增长/回收个数
maintenanceMilliseconds:维护间隔
运行机制:
在BorrowObject时,如果可以在FREES中取得对象则返回,如果获取失败,则当池中对象个数小于最大个数时,创建对象,否则等待对象返还并重试。
当使用完对象时可通过ReturnObject返还对象
对象池在指定的maintenanceMilliseconds的间隔内会维护池子的大小
可重载对象池的OnCreateObject创建对象,OnDestroyObject销毁对象,OnActiveObject激活对象和OnDeactivate使对象进入休眠
可使用USING语句在跳出代码块是自动返还对象
using(var po = ObjectPool.GetPoolPoolObject())
{
po.Object.xxx();
....
}
具体代码如下:
public abstract class ObjectPoolBase<TObjectPool, TObjectPoolDomain, TObject, TObjectDomain>
where TObjectPool : ObjectPoolBase<TObjectPool, TObjectPoolDomain, TObject, TObjectDomain>
where TObject : class
{
static ObjectPoolBase()
{
Instance = ContainerManager.Resolve<TObjectPool, TObjectPoolDomain> ();
ObjectPoolManager.Instance.RegisterObjectPool <TObjectPool, TObjectPoolDomain, TObject, TObjectDomain> (Instance);
}
public static TObjectPool Instance
{
get ;
private set ;
}
public static IPoolObject<TObject> GetPoolObject()
{
return new InternalPoolObject();
}
private ConcurrentBag<TObject> frees;
private ConcurrentDictionary<TObject, byte > borrowed;
private long count;
private int minSize;
private int growSize;
private int maxSize;
private long maintenanceMilliseconds;
private Timer maintenanceTimer;
private AutoResetEvent are;
private volatile bool exit;
protected ObjectPoolBase( int minSize, int growSize, int maintenanceMillseconds)
: this (minSize, int .MaxValue, growSize, maintenanceMillseconds)
{
}
public ObjectPoolBase( int minSize, int maxSize, int growSize, int maintenanceMillseconds)
{
CheckUtility.ArgumentPositiveNumber(minSize, " minSize " );
CheckUtility.ArgumentPositiveNumber(growSize, " growSize " );
CheckUtility.ArgumentPositiveNumber(maintenanceMillseconds, " maintenanceMillseconds " );
CheckUtility.ArgumentGreaterThanArgument(minSize, " minSize " , maxSize, " maxSize " );
this .minSize = minSize;
this .growSize = growSize;
this .maxSize = maxSize;
this .maintenanceMilliseconds = maintenanceMillseconds;
this .frees = new ConcurrentBag<TObject> ();
this .borrowed = new ConcurrentDictionary<TObject, byte > ();
this .count = 0 ;
this .are = new AutoResetEvent( false );
this .exit = false ;
this .maintenanceTimer = new Timer( this .TaskMaintenance, null , this .maintenanceMilliseconds, Timeout.Infinite);
}
public void Shutdown()
{
if ( this .exit)
{
return ;
}
this .exit = true ;
this .are.WaitOne();
}
private bool ShutdownIfExit()
{
if ( this .exit)
{
this .are.Set();
}
return this .exit;
}
private void WriteToLog( string messageFormat, params object [] args)
{
string message = CheckUtility.ArrayIsNullOrEmpty(args) ? messageFormat : string .Format(messageFormat, args);
LoggingWriter.WriteFormat( " [{0}] {1} {2} " , this .PoolName, message, this );
}
private void TaskMaintenance( object state)
{
this .WriteToLog( " Trigger Maintenance " );
if ( this .ShutdownIfExit())
{
return ;
}
Task.Factory.StartNew(() =>
{
if ( this .ShutdownIfExit())
{
return ;
}
this .WriteToLog( " Begin Maintenance " );
if (Interlocked.Read( ref this .count) <= this .maxSize)
{
lock ( this )
{
if (Interlocked.Read( ref this .count) <= this .maxSize)
{
if ( this .frees.Count > this .minSize)
{
this .MaintenanceDestroy(Math.Min( this .growSize, Math.Abs( this .frees.Count - this .minSize)));
}
else if ( this .frees.Count < this .minSize)
{
this .MaintenanceCreate(Math.Min( this .growSize, Math.Abs( this .frees.Count - this .minSize)));
}
}
}
}
this .WriteToLog( " After Maintenance " );
if ( this .ShutdownIfExit())
{
return ;
}
this .maintenanceTimer.Change( this .maintenanceMilliseconds, Timeout.Infinite);
}, TaskCreationOptions.LongRunning);
}
public TObject BorrowObject()
{
this .WriteToLog( " Before Borrow " );
TObject t;
do
{
if (! this .frees.TryTake( out t))
{
lock ( this )
{
while (! this .frees.TryTake( out t))
{
if ( this .exit)
{
throw new ObjectDisposedException( this .GetType().FullName);
}
long count = Interlocked.Read( ref this .count);
if (Interlocked.Read( ref this .count) >= this .maxSize)
{
Monitor.Wait( this , 10000 );
continue ;
}
else
{
long growSize = Math.Min( this .growSize, Math.Abs( this .count + this .growSize - this .maxSize));
if (growSize <= 0 )
{
Monitor.Wait( this , 10000 );
continue ;
}
else
{
this .MaintenanceCreate(growSize);
}
}
}
}
}
} while (! this .ActiveObject(t));
this .borrowed.TryAdd(t, 0 );
this .OnBorrow(t);
this .WriteToLog( " AfterBorrow " );
return t;
}
protected virtual void OnBorrow(TObject obj)
{
}
public void ReturnObject(TObject obj)
{
" obj " .NullArgument(obj);
this .WriteToLog( " Before Return " );
byte b;
if (! this .borrowed.TryRemove(obj, out b))
{
throw new InvalidOperationException(SR.InvalidObjectForPool);
}
if ( this .DeactiveObject(obj))
{
this .frees.Add(obj);
}
else
{
Interlocked.Decrement( ref this .count);
}
this .WriteToLog( " After Return " );
}
protected void MaintenanceCreate( long size)
{
this .WriteToLog( " Before Maintenance Create size: {0} " , size);
Parallel.For( 0 , size, (i) =>
{
if ( this .exit)
{
return ;
}
if (Interlocked.Read( ref this .count) < this .maxSize)
{
TObject t;
if ( this .CreateObject( out t))
{
this .frees.Add(t);
Interlocked.Increment( ref this .count);
}
}
});
this .WriteToLog( " After Maintenance Create " );
}
protected void MaintenanceDestroy( long size)
{
this .WriteToLog( " Before Maintenance Destroy size: {0} " , size);
Parallel.For( 0 , size, (i) =>
{
if ( this .exit)
{
return ;
}
TObject t;
if ( this .frees.TryTake( out t))
{
this .DestroyObject(t);
Interlocked.Decrement( ref this .count);
}
});
this .WriteToLog( " After Maintenance Destroy " );
}
private bool CreateObject( out TObject t)
{
this .WriteToLog( " Create Object " );
t = default (TObject);
try
{
t = this .OnCreateObject();
if ( null == t)
{
throw new NullReferenceException(SR.CreatedNullObjectForPool);
}
this .WriteToLog( " Object Created " );
return true ;
}
catch (Exception e)
{
LoggingWriter.WriteLog(e);
return false ;
}
}
protected virtual TObject OnCreateObject()
{
return ContainerManager.Resolve<TObject, TObjectDomain> ();
}
private bool ActiveObject(TObject t)
{
this .WriteToLog( " Active Object " );
try
{
this .OnActiveObject(t);
return true ;
}
catch (Exception e)
{
LoggingWriter.WriteLog(e);
this .DestroyObject(t);
return false ;
}
}
protected virtual void OnActiveObject(TObject obj)
{
}
private bool DeactiveObject(TObject t)
{
this .WriteToLog( " Deactive Object " );
try
{
this .OnDeactivateObject(t);
return true ;
}
catch (Exception e)
{
LoggingWriter.WriteLog(e);
this .DestroyObject(t);
return false ;
}
}
protected virtual void OnDeactivateObject(TObject obj)
{
}
private void DestroyObject(TObject t)
{
this .WriteToLog( " Destroy Object " );
try
{
byte b;
if ( this .borrowed.TryRemove(t, out b))
{
Interlocked.Decrement( ref this .count);
this .OnDestroyObject( ref t);
}
}
catch (Exception e)
{
LoggingWriter.WriteLog(e);
}
}
protected virtual void OnDestroyObject( ref TObject obj)
{
IDisposable disposable = obj as IDisposable;
if ( null != disposable)
{
try
{
disposable.Dispose();
}
catch (Exception e)
{
LoggingWriter.WriteLog(e);
}
}
else
{
obj = null ;
}
}
public virtual string PoolName
{
get
{
return typeof (TObjectPool).Name;
}
}
public override string ToString()
{
return string .Format( " [Pool Info] count: {0}, frees {1}, borrowed {2}, minSize {3}, maxSize {4} growSize {5} " ,
Interlocked.Read( ref this .count),
this .frees.Count,
this .borrowed.Count,
this .minSize,
this .maxSize,
this .growSize);
}
private class InternalPoolObject : IPoolObject<TObject> , IDisposable
{
private TObject obj;
public InternalPoolObject()
{
this .obj = null ;
}
public TObject Object
{
get
{
if ( null == this .obj)
{
this .obj = Instance.BorrowObject();
}
return this .obj;
}
}
public void Dispose()
{
if ( null != this .obj)
{
Instance.ReturnObject( this .obj);
}
}
}
}
分类: C#
标签: 对象池 ObjectPool
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息