好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

多线程环境下,手动创建数据库连接池

多线程环境下,手动创建数据库连接池

多线程环境下,手动创建数据库连接池

 

改进前分析:

由于之前做的项目占用sqlserver太多,程序运行时,导致sqlserver占用CPU 60%左右,内存占用1.6G左右,这种情况下可能会导致服务器的宕机或其它软件无法正常运行。而程序本身并没有占用太多CPU和内存。于是为减少sqlserver的占用,先后使用了两个解决办法:数据库连接池和数据缓冲池。

由于是在多线程环境下,必须要保证数据同步。而本人对EF没有深入研究,所以只好自己写。

数据库连接池思路:

1、当前软件中必须有且只有一个数据库连接池,所以使用单例模式进行定义。

2、为方便调用,方法使用static定义。

4、调用DBConnPool(数据库连接池)时,必须保证已经初始化必要的字段,而本类是静态类,所以使用静态构造方法,在静态构造方法中初始化必要的变量。

3、数据库连接们(sqlconneciton s)必须存储到一个字段中,这个字段是随时增长的(在小于最大连接数时),所以我使用的是List<Sqlconnection>。

4、一个连接在同一时间只能由一个代码调用,所以必须有属性加以区分,所以封装了自己的mySqlconn,里面包含两个字段:sqlconnection 和bool IsUsed,当 当前连接正在使用时,IsUsed=true,使用完毕IsUsed=false;另外,一般在DBHelper中,我们习惯使用using将sqlconnection包括起来,以便达到手动后释放的效果,这里有两个解决方法: 4.1:mySqlconn实现IDsipose接口,在dispose中 ,将IsUsed设置为false;

     4.2:不适用using,在sqlconnection使用完毕后,调用MySqlconn的Isused设置为false。本人使用的是这种方法。不过这两种理论上都可以。

5、本程序中没有用到事务处理,所以不对此进行设置,此思路和远吗也仅仅是针对当前项目。

总结 :数据库连接池整个的流程就是

  1、调用DBConnPool(数据库连接池)获取一个数据库连接。

  2、如果是第一次调用则首先调用DBConnPool的静态构造函数,对类进行初始化。

  3、获取数据库连接

    3.1、加锁(线程间同步)

    3.2、从List<MyConn>中获取一个MyConn.IsUsed属性为false的MyConn对象。如果没有则返回Null

    3.2、判断返回的MyConn对象是否为null,如果为null,则判断List<MyConn>.Count是否大于最大数据库连接数,如果大于,则sleep线程,并再次获取,如果小于,则创建新的MyConn对象,并将其放入到List集合中。

    3.3、将得到的MyConn对象的IsUsed设置为true。

    3.4、解锁

    3.5、返回MyConn对象

  4、MyConn对象使用完毕,设置MyConn.IsUsed为false。

贴上部分代码:

View Code

  public   static   MySqlConn GetConn()
   2           {
   3              MySqlConn conn =  null  ;
   4  
  5               lock   (syncget)
   6               {
   7                   if  (listMySqlConn ==  null  )
   8                   {
   9                      listMySqlConn =  new  List<MySqlConn> ();
  10                   }
  11                   if  (listMySqlConn.Count >  0  )
  12                   {
  13                      conn =  getConnFromCollection();
  14  
 15                       while  (conn ==  null  )
  16                       {
  17                           if  (listMySqlConn.Count >=  maxNum)
  18                           {
  19                              System.Threading.Thread.Sleep( 200  );
  20                              conn =  getConnFromCollection();
  21                           }
  22                           else 
 23                           {
  24                              conn =  new  MySqlConn(listMySqlConn.Count,  new   SqlConnection(connstr));
  25                               listMySqlConn.Add(conn);
  26                           }
  27                       }
  28                   }
  29                   else 
 30                   {
  31                      conn =  new  MySqlConn(listMySqlConn.Count, new   SqlConnection(connstr));
  32                       listMySqlConn.Add(conn);
  33                   }
  34                  conn.IsUsed =  true  ;
  35                   if  (conn.Sqlconn.State!= ConnectionState.Open)
  36                   {
  37                       conn.Sqlconn.Open();
  38                   }
  39               }
  40               return   conn;
  41           }
  42  
 43           private   static   MySqlConn getConnFromCollection()
  44           {
  45              MySqlConn conn =  null  ;
  46               foreach  (MySqlConn item  in   listMySqlConn)
  47               {
  48                   if  (! item.IsUsed)
  49                   {
  50                      conn =  item;
  51                       break  ;
  52                   }
  53               }
  54               return   conn;
  55          }

这个思路中没有涉及数据库连接池的关闭,由于本人这个项目是定时更新程序,每隔几分钟就要更新一次的,所以没有设定。

不过可以提供一个思路,在MyConn中增加一个字段LastUseTime,记录本连接上次使用时间。

在DBConnPool中定义一个System.Threading.Timer 变量,每隔2秒循环当前数据库集合,如果发现当前项上次使用时间距离现在超过5分钟,则将其销毁。(如有更好方法,请告诉我,不胜感激..)

下一次再写多线程环境下数据缓冲池的

 

 http://www.cnblogs.com/ysh2012/archive/2013/02/06/2900628.html

分类:  C#源码

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于多线程环境下,手动创建数据库连接池的详细内容...

  阅读:35次