以文本方式查看主题

-  中文XML论坛 - 专业的XML技术讨论区  (http://bbs.xml.org.cn/index.asp)
--  『 Dot NET,C#,ASP,VB 』  (http://bbs.xml.org.cn/list.asp?boardid=43)
----  万能对象池【C#实现】  (http://bbs.xml.org.cn/dispbbs.asp?boardid=43&rootid=&id=76599)


--  作者:卷积内核
--  发布时间:9/5/2009 8:58:00 AM

--  万能对象池【C#实现】
如果一种类型的对象需要经常被创建、销毁,为了提高性能,我们通常需要使用“池”技术,就如线程池、TCP连接池等一样。那么需要使用池技术的对象一般有哪些特征了?

(1)创建过程耗时

(2)不需要保存客户状态

(3)对象体积较大

(4)频繁创建/销毁

为了省事,我希望实现一个万能对象池组件,该对象池可以缓存任意类型的对象。下面给出对象池的接口:

public interface IObjectPool
    {
        //objType为缓存的对象的类型,cArgs为缓存对象的构造参数
        bool   Initialize(Type objType ,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 CallBackObjPool PoolShrinked  ;
        event CallBackObjPool MemoryUseOut  ; //内存分配失败
    }

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 Type destType = null ;
        private object[] ctorArgs = null ;
        private int minObjCount = 0 ;
        private int maxObjCount = 0 ;
        private int shrinkPoint = 0 ;
        private Hashtable hashTableObjs   = new Hashtable() ;
        private Hashtable hashTableStatus = new Hashtable() ; //key - isIdle        其中key就是hashcode
        private ArrayList keyList = new ArrayList() ;
        private bool supportReset = false ;
        #endregion

        IObjectPool 成员#region IObjectPool 成员
        public event CallBackObjPool PoolShrinked ;    
        public event CallBackObjPool MemoryUseOut ;

        public bool Initialize(Type objType, 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接口
            Type supType = 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(Exception ee) //分配内存失败!
            {
                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] ;
            IDisposable tar = 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)
                {
                    IPooledObjSupporter supporter = (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()
        {
            Type supType = typeof(System.IDisposable) ;
            if(supType.IsAssignableFrom(this.destType))
            {
                ArrayList list = (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
}


--  作者:卷积内核
--  发布时间:9/5/2009 8:58:00 AM

--  
对象在实现该接口后,就可以被对象池在收到归还的对象时重置其状态了。整个对象池的实现代码如下:

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 Type destType = null ;
        private object[] ctorArgs = null ;
        private int minObjCount = 0 ;
        private int maxObjCount = 0 ;
        private int shrinkPoint = 0 ;
        private Hashtable hashTableObjs   = new Hashtable() ;
        private Hashtable hashTableStatus = new Hashtable() ; //key - isIdle        其中key就是hashcode
        private ArrayList keyList = new ArrayList() ;
        private bool supportReset = false ;
        #endregion

        IObjectPool 成员#region IObjectPool 成员
        public event CallBackObjPool PoolShrinked ;    
        public event CallBackObjPool MemoryUseOut ;

        public bool Initialize(Type objType, 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接口
            Type supType = 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(Exception ee) //分配内存失败!
            {
                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] ;
            IDisposable tar = 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)
                {
                    IPooledObjSupporter supporter = (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()
        {
            Type supType = typeof(System.IDisposable) ;
            if(supType.IsAssignableFrom(this.destType))
            {
                ArrayList list = (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
}


W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
390.625ms