对象池化技术相关

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

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

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

 

//
// 对象池
//
//

using System;
using System.Collections.Generic;
using System.Text;

using System.Timers;
using System.Collections;

namespace objectPool
{
    /// <summary>
    /// 对象池
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    abstract class objectPool<T>
    {
        /// <summary>
        /// 最后取出对象时间
        /// </summary>
        private long longLastCheckOut = 0;
        /// <summary>
        /// 记录当前正在使用对象Hashtable
        /// </summary>
        private static Hashtable objLocked;
        /// <summary>
        /// 记录全部空闲及可用对象Hashtable
        /// </summary>
        private static Hashtable objUnLocked;
        /// <summary>
        /// 检查所有空闲及可用对象时间间隔:60秒(用于垃圾回收)
        /// </summary>
        private static long CLEANINTERVAL = 60 * 1000;

        /// <summary>
        /// 初始化成员变量
        /// </summary>
        static objectPool()
        {
            // 实例化对象
            objLocked = Hashtable.Synchronized(new Hashtable());
            objUnLocked = Hashtable.Synchronized(new Hashtable());
        }

        /// <summary>
        /// 创建一个新的对象
        /// </summary>
        /// <returns>对象实例</returns>
        protected abstract T Create();
        /// <summary>
        /// 检查特定对象有效性
        /// </summary>
        /// <param name="t">对象实例</param>
        /// <returns>是否有效 true or false</returns>
        protected abstract bool ValiDate(T t);
        /// <summary>
        /// 删除对象
        /// </summary>
        /// <param name="t">对象实例</param>
        protected abstract void Expire(T t);

        /// <summary>
        /// 构造函数
        /// </summary>
        internal objectPool()
        {
            // 取得现在时间
            longLastCheckOut = DateTime.Now.Ticks;
            // 实例化一个Timer对象
            Timer timer = new Timer();
            // 设置时间间隔
            timer.Interval = CLEANINTERVAL;
            timer.Enabled = true;
            // 到达时间间隔发生(垃圾回收)
            timer.Elapsed += delegate
            {
                lock (this)
                {
                    long longNow = DateTime.Now.Ticks;
                    try
                    {
                        foreach (DictionaryEntry entry in objUnLocked)
                        {
                            T t = (T)entry.Key;
                            // 超出垃圾回收时间间隔
                            if (longNow - (long)objUnLocked[t] > CLEANINTERVAL)
                            {
                                // 从可用对象中排除
                                objUnLocked.Remove(t);
                                // 删除对象
                                Expire(t);
                            }
                        }
                    }
                    catch (Exception)
                    { }
                }
            };
        }

        /// <summary>
        /// 从池中获取对象
        /// </summary>
        /// <returns>对象实例</returns>
        internal T GetObjectFromPool()
        {
            long longNow = DateTime.Now.Ticks;
            longLastCheckOut = longNow;
            T t;

            lock (this)
            {
                try
                {
                    foreach (DictionaryEntry entry in objUnLocked)
                    {
                        t = (T)entry.Key;
                        // 如果对象有效
                        if (ValiDate(t))
                        {
                            // 设置为非空闲对象
                            objUnLocked.Remove(t);
                            objLocked.Add(t, longNow);
                            return t;
                        }
                        else
                        {
                            // 删除对象
                            objUnLocked.Remove(t);
                            Expire(t);
                        }
                    }
                }
                catch (Exception)
                { }

                // 新创建对象
                t = Create();
                // 设置为正在使用对象
                objLocked.Add(t, longNow);
            }
            return t;
        }

        /// <summary>
        /// 将对象放入池中
        /// </summary>
        /// <param name="t">对象实例</param>
        internal void ReturnObjectToPool(T t)
        {
            if (!object.Equals(null, t))
            {
                lock (this)
                {
                    // 设置对象为空闲对象
                    objLocked.Remove(t);
                    objUnLocked.Add(t, DateTime.Now.Ticks);
                }
            }
        }
    }
}

DBConn类:

using System;
using System.Collections.Generic;
using System.Text;

using System.Data;
using System.Data.SqlClient;

namespace objectPool
{
    /// <summary>
    /// 数据库连接对象池
    /// </summary>
    class DBConn : objectPool<SqlConnection>
    {
        /// <summary>
        /// 私有构造函数
        /// </summary>
        private DBConn()
        { }
        /// <summary>
        /// 返回自身对象(Singleton)
        /// </summary>
        public static readonly DBConn Instance = new DBConn();

        /// <summary>
        /// 默认连接语句
        /// </summary>
        private static string strConnStr = @"Data Source=WORK0249\;Initial Catalog=AdventureWorks;Persist Security Info=True;User ID=sa;Password=sa";

        /// <summary>
        /// 连接语句(属性)
        /// </summary>
        public string StrConnStr
        {
            get
            {
                return strConnStr;
            }
            set
            {
                strConnStr = value;
            }
        }

        /// <summary>
        /// 创建数据库连接对象
        /// </summary>
        /// <returns>已打开的数据库连接对象</returns>
        protected override SqlConnection Create()
        {
            SqlConnection conn = new SqlConnection(strConnStr);
            conn.Open();
            return conn;
        }

        /// <summary>
        /// 验证连接状态
        /// </summary>
        /// <param name="t">数据库连接对象</param>
        /// <returns>连接状态Open : true   Close:false</returns>
        protected override bool ValiDate(SqlConnection t)
        {
            try
            {
                return !(t.State.Equals(ConnectionState.Closed));
            }
            catch (SqlException)
            {
                return false;
            }
        }

        /// <summary>
        /// 关闭数据库连接
        /// </summary>
        /// <param name="t">数据库连接对象</param>
        protected override void Expire(SqlConnection t)
        {
            try
            {
                t.Close();
            }
            catch (SqlException)
            { }
        }

        /// <summary>
        /// 从池中获取数据库连接
        /// </summary>
        /// <returns>数据库连接对象</returns>
        public SqlConnection BorrowDBConn()
        {
            try
            {
                return base.GetObjectFromPool();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 将连接对象放入池中
        /// </summary>
        /// <param name="conn">数据库连接对象</param>
        public void ReturnDBConn(SqlConnection conn)
        {
            base.ReturnObjectToPool(conn);
        }
    }
}

使用示例:

using System;
using System.Collections.Generic;
using System.Text;

using System.Data.SqlClient;

namespace objectPool
{
    class Program
    {
        static void Main(string[] args)
        {
            DBConn dbconn = DBConn.Instance;

            // 从池中取出对象
            SqlConnection conn = dbconn.BorrowDBConn();

            string strSql = "SELECT AddressID, AddressLine1, AddressLine2, City, StateProvinceID, PostalCode, " +
                "rowguid, ModifiedDate FROM Person.Address";

            SqlCommand command = new SqlCommand(strSql, conn);
            SqlDataReader reader = command.ExecuteReader();

            while (reader.Read())
            {
                Console.Write(reader[0]);
            }

            // 将对象放入池中
            dbconn.ReturnDBConn(conn);

            Console.Read();
        }
    }
}
posted @ 2011-01-28 12:55  KidYang  阅读(434)  评论(0编辑  收藏  举报