在系统设计中,经常会使用“池”的概念。比如数据库连接池,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();}}
}