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

分类: 读书笔记2009-11-09 15:46 747人阅读 评论(0) 收藏 举报
数据库连接池多线程object数据库exceptionstring

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

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

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. namespace SqlPool
  6. {
  7. class Program
  8. {
  9. static void Main(string[] args)
  10. {
  11. DBConnectionSingleton pool;
  12. //获得数据库连接池的单例模式。
  13. pool = DBConnectionSingleton.Instance;
  14. DBConnectionSingleton.ConnectionString = @"Data Source=192.168.168.251/Sql2005;Initial Catalog=XX;User ID=sa;Password=777";
  15. SqlConnection myConnection = pool.BorrowDBConnection();
  16. pool.ReturnDBConnecion(myConnection);
  17. System.Threading.Thread.Sleep(5000);
  18. }
  19. }
  20. }

4 多线程应用:数据库连接池相关推荐

  1. Flask和mysql多线程_数据库连接池Flask-SQLAlchemy中多线程安全的问题

    使用flask-sqlalchemy写代码码到一半,突然想到,Session是否是线程安全的?于是上官方文档,答案是否! 那问题来了,怎么破?因为它会牵涉到多线程情况下,调用rollback导致的不可 ...

  2. 【Python SQLAlchemy】数据库连接池SQLAlchemy中多线程安全的问题

    问题描述 写了一个apscheduler定时任务 里面用到SQLAlchemy在同一时间点开启了18个任务,用于更新18个表 但是最终看数据库表的时候,发现有2个表未更新.查看打印日志均正常,查找原因 ...

  3. Python爬取股票数据存入mysql数据库,获取股票(最新、最高、今开、成交量、成交额、量比、换手率、涨幅等)支持多线程+数据库连接池

    项目简介 (Python)爬虫 + MySQL + Redis项目. 爬取下来的数据可用于后续的数据分析(我计划将其用于我的毕业设计). 未来会将数据分析的可视化部署到服务器上, 并添加股票降价通知的 ...

  4. python多线程并发访问数据库连接池原理以及代码

    现状 在工作中难免会使用数据库,为了能够高效并发访问数据库,数据库连接池必不可少,由于本站copy模式盛行,导致数据库连接池被错误使用,遇到错误甚至追求能跑通就行. 本文就python版本的数据库链接 ...

  5. mysql 连接池 多线程_4 多线程应用:数据库连接池 | 学步园

    首先说明一下:这个例子是来源于[C#线程参考手册]参考手册内的一个例子,在这个我只是想研究一下她的设计原理. 具体好用不好用,因为没有做具体项目的测试,所以提醒大家注意. 1 设计思路: 1.1 在程 ...

  6. 聊一个不常见的面试题:为什么数据库连接池不采用 IO 多路复用?

    欢迎关注方志朋的博客,回复"666"获面试宝典 今天我们聊一个不常见的 Java 面试题:为什么数据库连接池不采用 IO 多路复用? 这是一个非常好的问题.IO多路复用被视为是非常 ...

  7. 为什么数据库连接池不采用 IO 多路复用?

    欢迎关注方志朋的博客,回复"666"获面试宝典 接着,今天我们聊一个不常见的 Java 面试题:为什么数据库连接池不采用 IO 多路复用? 这是一个非常好的问题.IO多路复用被视为 ...

  8. 数据库连接池为什么要用threadlocal呢?不用会怎样?

    点击关注公众号,Java干货及时送达 来源:blog.csdn.net/qq_42405666/article/details/108258820 这个问题我疑问了很久很久,主要如下截图. 个连接对应 ...

  9. 数据库连接池到底应该设多大?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:kelgon www.jianshu.com/p/a8f65 ...

最新文章

  1. TMS320F28335项目开发记录2_CCS与JTAG仿真器连接问题汇总
  2. CV04-UNet笔记
  3. DL之AlexNet:利用卷积神经网络类AlexNet实现猫狗分类识别(图片数据增强→保存h5模型)
  4. YbtOJ-森林之和【dp】
  5. 前端常见的加密算法介绍
  6. 比特飞解决方案大汇总,你的贴身家教
  7. Android 系统性能优化(41)---Android代码内存优化建议-OnTrimMemory优化
  8. 2022年中国商业十大热点展望:共同富裕、碳达峰碳中和、创新、数字化、新国货.........
  9. 可变cell,自适应cell,理解iOS 8中的Self Sizing Cells和Dynamic Type
  10. JavaWeb开发必会技巧1——导入jar包
  11. BZOJ2330:[SCOI2011]糖果(差分约束)
  12. 立体栅格地图_三维栅格地图构建之三:点集到栅格的投射
  13. 【python 监控报警】python自动发钉钉机器人报警
  14. linux服务器双网卡配置,linux 关于主机服务器双网卡bond配置
  15. 批量下载网页链接---数据集批量下载
  16. EXCEL文本函数-数字小写换大写-英文大小写互换
  17. android动态mac地址,android 设备唯一码的获取,Cpu号,Mac地址
  18. 破解魔术的秘密(一)——直面秘密的角落
  19. java excel 判断组重复_Java判断Excel某列是否有重复值
  20. 实战智能推荐系统(5)-- 推荐系统评价指标

热门文章

  1. java批量下载图片_Java批量写入文件和下载图片的示例代码
  2. 基于ESP32学习MicroPython(三): 流水灯案例
  3. IPV4 IPV6 DHCP中继服务器之思科交换机配置
  4. 戴尔Inspiron 灵越 14R(N4120)加装固态硬盘
  5. GeneXus学习记录——创建KB(KnowledgeBase/知识库)
  6. dpi 、 dip 、分辨率、屏幕尺寸、px、density 关系以及换算
  7. java empty_Java Optional empty()用法及代码示例
  8. 齐枭飞 Vue系列--vue的图片路径,和背景图片路径打包后错误解决
  9. 黑马程序员——Java字符流、字节流IO流
  10. [转]数码照片的JPG文件高级信息(用C#读取图片的EXIF信息)