新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论.NET,C#,ASP,VB技术
    [返回] 计算机科学论坛计算机技术与应用『 Dot NET,C#,ASP,VB 』 → 用C#建立通用对象池 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 6677 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 用C#建立通用对象池 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 Dot NET,C#,ASP,VB 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 用C#建立通用对象池

    在系统设计中,经常会使用“池”的概念。比如数据库连接池,socket连接池,线程池,组件队列。“池”可以节省对象重复创建和初始化所耗费 的时间,可以简化对象获取和使用的过程。对于那些被系统频繁请求和使用的对象,如果使用这种机制,可以使系统性能得到很大提高。特别象数据库连接这种对 象,客户端与数据库服务器端建立连接时,是比较慢的,如果每次进行数据库操作,都要先进行数据库连接,系统效率将非常低下。

    “池”的概念就是将被使用的对象事先创建好,保存在列表中,供客户端取用。当客户端取得一个对象时,这个对象就已经是按照特定上下文环境初始化好,马上即 可使用的了。当客户端使用完毕,需要将对象归还给“池”,最后,在系统生命期结束时,由“池”统一释放这些对象。从另一个概念上来说,这也是一种“以空间 换时间”的做法,我们在内存中保存一系列整装待命的对象,供人随时差遣。与系统效率相比,这些对象所占用的内存空间太微不足道了。

    “池”的结构是通用的,就是不管他里面保存的是哪一种对象,他的工作方法都基本不变。无非是初始化一系列对象,然后提供一个获取可用对象,一个归还对象的接口。

    基于这种考虑,我们可以建立一个通用的对象池,只要某些对象符合“一些基本要求”(这个基本要求,可以使用Interface模式来限定),就可以使用通用对象池来存取和管理。

    创建一个接口,用于限定对象池中所保存的对象的基本行为:

    复制C#代码保存代码public interface IDynamicObject

    {
        void Create(Object param);
        Object GetInnerObject();
        bool IsValidate();
        void Release();
    }

    我们在对象池中存放的对象,必须继承上面的接口,并实现接口定义的每一个方法。

    Create方法中,用户可以用来创建实际的对象,如建立数据库连接,并打开这个连接;GetInnerObject方法,使用户可以返回这个实际 的对象,如一个SqlConnection对象;IsValidate方法是用来判断用户自定义对象的有效性的,是对象池决定是否重新创建对象的标志; Release方法中,用户可以进行资源释放工作。

    有了上面的接口定义,为我们可以在列表中保存用户自定义对象打下了基础。下面就是要实现这个ObjectPool了。

    用户自定义对象在我们的ObjectPool中,可以用列表存储,如ArrayList或者Hashtable,为了表示每个用户对象的状态,我们 还需要将用户自定义对象包装一下,然后在放到列表中保存。下面定义了一个ObjectPool类的子类,用于包装用户自定义对象:

    复制C#代码保存代码private class PoolItem

    {
        private IDynamicObject _object;
        private bool _bUsing;
        private Type _type;
        private Object _CreateParam;

        public PoolItem(Type type, Object param)
        {
            _type = type;
            _CreateParam = param;
            Create();
        }

        private void Create()
        {
            _bUsing = false;
            _object = (IDynamicObject) System.Activator.CreateInstance(_type);
            _object.Create(_CreateParam);
        }

        public void Recreate()
        {
            _object.Release();
            Create();
        }

        public void Release()
        {
            _object.Release();
        }

        public Object InnerObject
        {
            get { return _object.GetInnerObject(); }
        }

        public int InnerObjectHashcode
        {
            get { return InnerObject.GetHashCode(); }
        }

        public bool IsValidate
        {
            get { return _object.IsValidate(); }
        }

        public bool Using
        {
            get { return _bUsing; }
            set { _bUsing = value; }
        }
    }// class PoolItem

    这个类,一个关键的属性是Using,该属性表示对象是否正在被被用户使用。注意,PoolItem创建时,接受一个Object类型的Param参 数,这个参数最后被传递给用户自定义对象的Create方法。用户可以利用这一点,在创建ObjectPool时指定一些参数,供其自定义对象在创建时使 用。比如创建SocketPool时,将服务器IP,端口通过Param传递给自定义对象的Create方法,用户就可以在Create方法中连接指定的 服务器了。

    以下是ObjectPool的具体实现代码:

    复制C#代码保存代码public sealed class ObjectPool

    {
        private Int32 _nCapacity;
        private Int32 _nCurrentSize;
        private Hashtable _listObjects;
        private ArrayList _listFreeIndex;
        private ArrayList _listUsingIndex;
        private Type _typeObject;
        private Object _objCreateParam;

        public ObjectPool(Type type, Object create_param, Int32 init_size, Int32 capacity)
        {
            if (init_size < 0 || capacity < 1 || init_size > capacity)
            {
                throw (new Exception("Invalid parameter!"));
            }

            _nCapacity = capacity;
            _listObjects = new Hashtable(capacity);
            _listFreeIndex = new ArrayList(capacity);
            _listUsingIndex = new ArrayList(capacity);
            _typeObject = type;
            _objCreateParam = create_param;

            for (int i = 0; i < init_size; i++)
            {
                PoolItem pitem = new PoolItem(type, create_param);
                _listObjects.Add(pitem.InnerObjectHashcode, pitem);
                _listFreeIndex.Add(pitem.InnerObjectHashcode);
            }

            _nCurrentSize = _listObjects.Count;
        }

        public void Release()
        {
            lock (this)
            {
                foreach (DictionaryEntry de in _listObjects)
                {
                    ((PoolItem) de.Value).Release();
                }
                _listObjects.Clear();
                _listFreeIndex.Clear();
                _listUsingIndex.Clear();
            }
        }

        public Int32 CurrentSize
        {
            get { return _nCurrentSize; }
        }

        public Int32 ActiveCount
        {
            get { return _listUsingIndex.Count; }
        }

        public Object GetOne()
        {
            lock (this)
            {
                if (_listFreeIndex.Count == 0)
                {
                    if (_nCurrentSize == _nCapacity)
                    {
                        return null;
                    }
                    PoolItem pnewitem = new PoolItem(_typeObject, _objCreateParam);
                    _listObjects.Add(pnewitem.InnerObjectHashcode, pnewitem);
                    _listFreeIndex.Add(pnewitem.InnerObjectHashcode);
                    _nCurrentSize++;
                }

                Int32 nFreeIndex = (Int32) _listFreeIndex[0];
                PoolItem pitem = (PoolItem) _listObjects[nFreeIndex];
                _listFreeIndex.RemoveAt(0);
                _listUsingIndex.Add(nFreeIndex);

                if (!pitem.IsValidate)
                {
                    pitem.Recreate();
                }

                pitem.Using = true;
                return pitem.InnerObject;
            }
        }

        public void FreeObject(Object obj)
        {
            lock (this)
            {
                int key = obj.GetHashCode();
                if (_listObjects.ContainsKey(key))
                {
                    PoolItem item = (PoolItem) _listObjects[key];
                    item.Using = false;
                    _listUsingIndex.Remove(key);
                    _listFreeIndex.Add(key);
                }
            }
        }

        public Int32 DecreaseSize(Int32 size)
        {
            Int32 nDecrease = size;
            lock (this)
            {
                if (nDecrease <= 0)
                {
                    return 0;
                }
                if (nDecrease > _listFreeIndex.Count)
                {
                    nDecrease = _listFreeIndex.Count;
                }

                for (int i = 0; i < nDecrease; i++)
                {
                    _listObjects.Remove(_listFreeIndex[i]);
                }

                _listFreeIndex.Clear();
                _listUsingIndex.Clear();

                foreach (DictionaryEntry de in _listObjects)
                {
                    PoolItem pitem = (PoolItem) de.Value;
                    if (pitem.Using)
                    {
                        _listUsingIndex.Add(pitem.InnerObjectHashcode);
                    }
                    else
                    {
                        _listFreeIndex.Add(pitem.InnerObjectHashcode);
                    }
                }
            }
            _nCurrentSize -= nDecrease;
            return nDecrease;
        }
    }


       收藏   分享  
    顶(1)
      




    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2009/9/5 9:02:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 Dot NET,C#,ASP,VB 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客2
    发贴心情 
    虽然.NET对数据库连接已经提供了连接池,但是,经测试,使用上述通用对象池实现的数据库连接池,效率要比直接使用.NET管理的连接池高。因为他减少了Open和Close操作,从而节省了时间。

    代码如下:

    复制C#代码保存代码public class DBPool

    {
        private class SqlConnectionObject : IDynamicObject
        {
            private SqlConnection _SqlConn;

            public SqlConnectionObject()
            {
                _SqlConn = null;
            }

            #region IDynamicObject Members

            public void Create(Object param)
            {
                String strConn = (String) param;
                _SqlConn = new SqlConnection(strConn);
                _SqlConn.Open();
            }

            public Object GetInnerObject()
            {
                // TODO: Add SqlConnectionObject.GetInnerObject implementation
                return _SqlConn;
            }

            public bool IsValidate()
            {
                return (_SqlConn != null
                    && _SqlConn.GetHashCode() > 0
                    && _SqlConn.State == ConnectionState.Open);
            }

            public void Release()
            {
                // TODO: Add SqlConnectionObject.Release implementation
                _SqlConn.Close();
            }

            #endregion
        }

        private ObjectPool _Connections;

        public DBPool(string connection, int initcount, int capacity)
        {
            if (connection == null || connection == "" || initcount < 0 || capacity < 1)
            {
                throw (new Exception("Invalid parameter!"));
            }
            _Connections = new ObjectPool(typeof(SqlConnectionObject), connection, initcount, capacity);
        }

        public SqlConnection GetConnection()
        {
            return (SqlConnection) _Connections.GetOne();
        }

        public void FreeConnection(SqlConnection sqlConn)
        {
            _Connections.FreeObject(sqlConn);
        }

        public void Release()
        {
            _Connections.Release();
        }

        public int Count
        {
            get { return _Connections.CurrentSize; }
        }

        public int UsingCount
        {
            get { return _Connections.ActiveCount; }
        }

        public int DecreaseSize(int size)
        {
            return _Connections.DecreaseSize(size);
        }
    } // DBPool

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2009/9/5 9:04:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 Dot NET,C#,ASP,VB 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/4/19 23:48:53

    本主题贴数2,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    78.125ms