好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

.NET 并行库写的对象池

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

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于.NET 并行库写的对象池的详细内容...

  阅读:43次