.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://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息