4 多线程应用:数据库连接池

转载 2013年12月05日 14:30:29
 

4 多线程应用:数据库连接池

分类: 读书笔记 747人阅读 评论(0) 收藏 举报

首先说明一下:这个例子是来源于【C#线程参考手册】参考手册内的一个例子,在这个我只是想研究一下她的设计原理。

    具体好用不好用,因为没有做具体项目的测试,所以提醒大家注意。     

        

1 设计思路:

   1.1 在程序的全局利用单例模式建立一个数据库连接池对象。

   1.2 获得数据库连接方法BorrowDBConnection()。

        这个方法的作用如下:

             如果【待清理的池】内DB连接对象不是关闭状态,则添加到【DB连接池】,继续使用。

             如果【待清理的池】内DB连接对象是关闭状态,则DB连接被移除【待清理的池】,之后被关闭。

             如果【待清理的池】不存在DB连接对象,则创建DB连接对象后,附加到【DB连接池】内,然后使用她。

  1.3 返回数据库连接给【待清理的池】,方法是ReturnObjectToPool()。

             【DB连接池】删除DB连接对象。

             【待清理的池】追加DB连接对象。

   1.4 延迟DB连接对象的垃圾回收事件

              通过Timer的Elapsed事件,来实现【待清理的池】内的DB连接对象的关闭处理。

 

2 UML图例:

   

   这里要说明的是,为什么要继承ObjectPool类呢?

       因为ObjectPool类的结构对于所有使用池、可手动释放资源的对象是通用的。

 

3 具体代码如下:

     3.1 ObjectPool类(真的很通用的一个类,设计的很好,感觉可以继承她做任何事)

      

[c-sharp] view plaincopy
  1. using System;  
  2. using System.Collections;  
  3. using System.Timers;  
  4. using System.Text;  
  5.   
  6. namespace SqlPool  
  7. {  
  8.     public abstract class ObjectPool  
  9.     {  
  10.         /// <summary>  
  11.         /// //当前日期时间刻度值,用户判断连接是否超时  
  12.         /// </summary>  
  13.         private long _lastCheckOut;  
  14.         /// <summary>  
  15.         /// 使用对象池  
  16.         /// </summary>  
  17.         private static Hashtable locked;   
  18.         /// <summary>  
  19.         /// 清理对象池  
  20.         /// </summary>  
  21.         private static Hashtable unlocked;  
  22.         internal static long GARBAGE_INTERVAL = 5 * 1000;  
  23.   
  24.         /// <summary>  
  25.         /// 构造函数1,说明了两个池是同步的。  
  26.         /// </summary>  
  27.         static ObjectPool()  
  28.         {  
  29.             locked = Hashtable.Synchronized(new Hashtable());  
  30.             unlocked = Hashtable.Synchronized(new Hashtable());  
  31.         }  
  32.   
  33.         /// <summary>  
  34.         /// 初始化时间间隔,时间间隔触发事件,释放清理对象池的对象  
  35.         /// </summary>  
  36.         internal ObjectPool()  
  37.         {  
  38.             _lastCheckOut = DateTime.Now.Ticks;  
  39.             System.Timers.Timer aTimer = new System.Timers.Timer();  
  40.             aTimer.Enabled = true;  
  41.             aTimer.Interval = GARBAGE_INTERVAL;  
  42.             aTimer.Elapsed += new ElapsedEventHandler(CollectGarbage);  
  43.         }  
  44.   
  45.        /// <summary>  
  46.        /// 建立一个数据库连接  
  47.        /// </summary>  
  48.        /// <returns></returns>  
  49.         protected abstract object Create();  
  50.   
  51.         /// <summary>  
  52.         /// 判断数据库连接是否正常  
  53.         /// </summary>  
  54.         /// <param name="o"></param>  
  55.         /// <returns></returns>  
  56.         protected abstract bool Validate(object o);  
  57.   
  58.         /// <summary>  
  59.         /// 延迟的连接被关闭  
  60.         /// </summary>  
  61.         /// <param name="o"></param>  
  62.         protected abstract void Expire(object o);  
  63.   
  64.         /// <summary>  
  65.         /// Sql连接超出指定时间后的垃圾回收  
  66.         /// </summary>  
  67.         /// <param name="sender"></param>  
  68.         /// <param name="ea"></param>  
  69.         private void CollectGarbage(object sender, ElapsedEventArgs ea)  
  70.         {  
  71.             lock (this)  
  72.             {  
  73.                 object o;  
  74.                 long now = DateTime.Now.Ticks;  
  75.                 IDictionaryEnumerator e = unlocked.GetEnumerator();  
  76.   
  77.                 try {  
  78.                     while (e.MoveNext())  
  79.                     {  
  80.                         o = e.Key;  
  81.                         if(now-((long)unlocked[o])>GARBAGE_INTERVAL)  
  82.                         {  
  83.                             unlocked.Remove(o);  
  84.                             Expire(o);  
  85.                             o = null;  
  86.                         }  
  87.                     }  
  88.                 }  
  89.                 catch{}  
  90.             }  
  91.         }  
  92.   
  93.   
  94.         /// <summary>  
  95.         /// 获得数据库连接  
  96.         /// </summary>  
  97.         /// <returns></returns>  
  98.         internal object GetObjectFromPool()  
  99.         {  
  100.             long now = DateTime.Now.Ticks;  
  101.             _lastCheckOut = now;  
  102.             object o = null;  
  103.   
  104.             lock (this)  
  105.             {  
  106.                 try  
  107.                 {  
  108.                     foreach (DictionaryEntry myEntry in unlocked)  
  109.                     {  
  110.                         o = myEntry.Key;  
  111.   
  112.                         if (Validate(o))  
  113.                         {  
  114.                             unlocked.Remove(o);  
  115.                             locked.Add(o, now);  
  116.                             return (o);  
  117.                         }  
  118.                         else  
  119.                         {  
  120.                             unlocked.Remove(o);  
  121.                             Expire(o);  
  122.                             o = null;  
  123.                         }  
  124.                     }  
  125.                 }  
  126.   
  127.                 catch (Exception) { }  
  128.                 o = Create();  
  129.                 locked.Add(o, now);  
  130.             }  
  131.             return o;  
  132.         }  
  133.   
  134.         /// <summary>  
  135.         /// 清除数据库连接  
  136.         /// </summary>  
  137.         /// <param name="o"></param>  
  138.         internal void ReturnObjectToPool(object o)  
  139.         {  
  140.             if (o != null)  
  141.             {  
  142.                 lock (this)  
  143.                 {  
  144.                     locked.Remove(o);  
  145.                     unlocked.Add(o, DateTime.Now.Ticks);  
  146.                 }  
  147.             }  
  148.         }  
  149.     }  
  150. }  

 

    3.2 DBConnectionSingleton类 -   数据库连接池(实现了ObjectPool类的Create,Validate,Expire方法,并使用了单例模式)

    

[c-sharp] view plaincopy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4. using System.Data.SqlClient;  
  5.   
  6. namespace SqlPool  
  7. {  
  8.     class DBConnectionSingleton:ObjectPool  
  9.     {  
  10.         private DBConnectionSingleton() { }  
  11.   
  12.         /// <summary>  
  13.         /// 以单例模式创建数据库连接池  
  14.         /// </summary>  
  15.         public static readonly DBConnectionSingleton Instance = new DBConnectionSingleton();  
  16.   
  17.         private static string _connectionString = @"Data Source=192.168.168.251/Sql2005;Initial Catalog=XX;User ID=sa;Password=777";  
  18.   
  19.         /// <summary>  
  20.         /// 数据库连接字符串  
  21.         /// </summary>  
  22.         public static string ConnectionString  
  23.         {  
  24.             set {  
  25.                 _connectionString = value;  
  26.             }  
  27.             get  
  28.             {  
  29.                 return _connectionString;  
  30.             }  
  31.         }  
  32.   
  33.         /// <summary>  
  34.         /// 创建数据库连接  
  35.         /// </summary>  
  36.         /// <returns></returns>  
  37.         protected override object Create()  
  38.         {  
  39.             SqlConnection temp = new SqlConnection(_connectionString);  
  40.             temp.Open();  
  41.             return temp;  
  42.         }  
  43.   
  44.         /// <summary>  
  45.         /// 判断DB是否已连接  
  46.         /// </summary>  
  47.         /// <param name="o"></param>  
  48.         /// <returns></returns>  
  49.         protected override bool Validate(object o)  
  50.         {  
  51.             try   
  52.             {  
  53.                 SqlConnection temp = (SqlConnection)o;  
  54.                 return (!((temp.State.Equals(System.Data.ConnectionState.Closed))));  
  55.             }  
  56.             catch  
  57.             {  
  58.                 return false;  
  59.             }  
  60.         }  
  61.   
  62.         /// <summary>  
  63.         /// 关闭DB连接  
  64.         /// </summary>  
  65.         /// <param name="o"></param>  
  66.         protected override void Expire(object o)  
  67.         {  
  68.             try  
  69.             {  
  70.                 ((SqlConnection)o).Close();  
  71.             }  
  72.             catch {   
  73.             }  
  74.         }  
  75.   
  76.         /// <summary>  
  77.         /// 获得DB连接  
  78.         /// </summary>  
  79.         /// <returns></returns>  
  80.         public SqlConnection BorrowDBConnection()  
  81.         {  
  82.             try  
  83.             {  
  84.                 return ((SqlConnection)base.GetObjectFromPool());  
  85.             }  
  86.             catch(Exception e) {  
  87.                 throw e;  
  88.             }  
  89.         }  
  90.   
  91.         /// <summary>  
  92.         /// 清除DB连接  
  93.         /// </summary>  
  94.         /// <param name="e"></param>  
  95.         public void ReturnDBConnecion(SqlConnection e)  
  96.         {  
  97.             base.ReturnObjectToPool(e);  
  98.         }  
  99.     }  
  100. }  

  

     3.3 Main函数

    

[c-sharp] view plaincopy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4. using System.Data.SqlClient;  
  5.   
  6. namespace SqlPool  
  7. {  
  8.     class Program  
  9.     {  
  10.         static void Main(string[] args)  
  11.         {  
  12.             DBConnectionSingleton pool;  
  13.   
  14.             //获得数据库连接池的单例模式。  
  15.             pool = DBConnectionSingleton.Instance;  
  16.               
  17.             DBConnectionSingleton.ConnectionString = @"Data Source=192.168.168.251/Sql2005;Initial Catalog=XX;User ID=sa;Password=777";  
  18.   
  19.             SqlConnection myConnection = pool.BorrowDBConnection();  
  20.             pool.ReturnDBConnecion(myConnection);  
  21.             System.Threading.Thread.Sleep(5000);  
  22.         }  
  23.     }  
  24. }  

    

从零开始实现Java多线程数据库连接池(附一个神秘的问题)

本例采用mysql数据库,因此请先下载mysql-connection.jar 众所周知,创建数据库连接需要消耗较多的资源,且创建时间也较长。如果网站一天100万PV(假设每个页面都有DB读取或修改操...
  • soonfly
  • soonfly
  • 2017年05月25日 16:54
  • 4382

修改和优化mysql的线程连接池

本文主要记录本人关于修改和优化mysql连接池代码的记录,注意,本文中提出的方法或实现并不是mysql官方企业版中的实现,只是个人尝试。 概述: 在mysql5.5的企业版中似乎已经提供了真正意义上...
  • gao1738
  • gao1738
  • 2015年01月18日 20:15
  • 846

线程池 和数据库连接池

线程池的原理和连接池的原理    线程池的原理:            来看一下线程池究竟是怎么一回事?其实线程池的原理很简单,类似于操作系统中的缓冲区的概念,它的流程如下:先启动若干数量的线...
  • u011244446
  • u011244446
  • 2015年05月14日 20:09
  • 1483

JAVA数据库连接池实现

连接池的管理用了了享元模式,这里对连接池进行简单设计。 一、设计思路      1.连接池配置属性DBbean:里面存放可以配置的一些属性      2.连接池接口IConnectionPool...
  • lulongzhou_llz
  • lulongzhou_llz
  • 2015年03月18日 11:24
  • 2445

MySQL MySql连接数与线程池

连接数 1、  查看允许的最大并发连接数 SHOW VARIABLES LIKE 'max_connections'; MySql连接数与线程池" title="MySQL MySq...
  • z69183787
  • z69183787
  • 2016年10月21日 16:34
  • 2098

【服务器编程】多线程安全数据库连接池

某风平浪静的晚上,我和多线程搅上劲,如何在多线程环境安全创建连接池、释放、使用,想了很久,写了很久,写出了如下代码,感觉也很多bug吧。 发表此文,谨表示我今晚不知道为什么如此 较真,很想做到完美,...
  • Jammg
  • Jammg
  • 2016年07月05日 23:56
  • 1760

多线程访问数据库

android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5)上面的问题,是因为每次创建SQLit...
  • zhangyongfeiyong
  • zhangyongfeiyong
  • 2016年05月23日 09:47
  • 955

线程池和数据库连接池的原理

线程池的原理:            来看一下线程池究竟是怎么一回事?其实线程池的原理很简单,类似于操作系统中的缓冲区的概念,它的流程如下:先启动若干数量的线程,并让这些线程都处于睡眠状...
  • duchao123duchao
  • duchao123duchao
  • 2015年07月30日 18:20
  • 1863

线程池和mysql连接池的实现

  • 2015年07月03日 11:10
  • 8KB
  • 下载

多线程情况下创建连接池

JAVA数据库连接池实现 博客分类: • 数据库连接池 JAVA数据库连接池连接池原理连接池实现JAVA连接池 连接池的管理用了了享元模式,这里对连接池进行简单设计。 一、设计思路 ...
  • zcl_love_wx
  • zcl_love_wx
  • 2016年05月05日 22:23
  • 1946
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:4 多线程应用:数据库连接池
举报原因:
原因补充:

(最多只允许输入30个字)