zoukankan      html  css  js  c++  java
  • .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#
  • 相关阅读:
    北京六环附近及往内的可驾驶道路网络(路网graph为连通图)
    OSM数据处理-python工具包
    小程序踩坑
    小程序基本配置
    JavaScript 基础(四):Array
    MYSQL--慎用group_concat()
    真正高效的SQLSERVER分页查询
    PhpStorm Git 操作
    linux 查看当前目录文件的大小
    @PostConstruct和@PreDestroy的使用说明
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2958398.html
Copyright © 2011-2022 走看看