4 多线程应用:数据库连接池
4 多线程应用:数据库连接池
首先说明一下:这个例子是来源于【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类(真的很通用的一个类,设计的很好,感觉可以继承她做任何事)
- using System;
- using System.Collections;
- using System.Timers;
- using System.Text;
- namespace SqlPool
- {
- public abstract class ObjectPool
- {
- /// <summary>
- /// //当前日期时间刻度值,用户判断连接是否超时
- /// </summary>
- private long _lastCheckOut;
- /// <summary>
- /// 使用对象池
- /// </summary>
- private static Hashtable locked;
- /// <summary>
- /// 清理对象池
- /// </summary>
- private static Hashtable unlocked;
- internal static long GARBAGE_INTERVAL = 5 * 1000;
- /// <summary>
- /// 构造函数1,说明了两个池是同步的。
- /// </summary>
- static ObjectPool()
- {
- locked = Hashtable.Synchronized(new Hashtable());
- unlocked = Hashtable.Synchronized(new Hashtable());
- }
- /// <summary>
- /// 初始化时间间隔,时间间隔触发事件,释放清理对象池的对象
- /// </summary>
- internal ObjectPool()
- {
- _lastCheckOut = DateTime.Now.Ticks;
- System.Timers.Timer aTimer = new System.Timers.Timer();
- aTimer.Enabled = true;
- aTimer.Interval = GARBAGE_INTERVAL;
- aTimer.Elapsed += new ElapsedEventHandler(CollectGarbage);
- }
- /// <summary>
- /// 建立一个数据库连接
- /// </summary>
- /// <returns></returns>
- protected abstract object Create();
- /// <summary>
- /// 判断数据库连接是否正常
- /// </summary>
- /// <param name="o"></param>
- /// <returns></returns>
- protected abstract bool Validate(object o);
- /// <summary>
- /// 延迟的连接被关闭
- /// </summary>
- /// <param name="o"></param>
- protected abstract void Expire(object o);
- /// <summary>
- /// Sql连接超出指定时间后的垃圾回收
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="ea"></param>
- private void CollectGarbage(object sender, ElapsedEventArgs ea)
- {
- lock (this)
- {
- object o;
- long now = DateTime.Now.Ticks;
- IDictionaryEnumerator e = unlocked.GetEnumerator();
- try {
- while (e.MoveNext())
- {
- o = e.Key;
- if(now-((long)unlocked[o])>GARBAGE_INTERVAL)
- {
- unlocked.Remove(o);
- Expire(o);
- o = null;
- }
- }
- }
- catch{}
- }
- }
- /// <summary>
- /// 获得数据库连接
- /// </summary>
- /// <returns></returns>
- internal object GetObjectFromPool()
- {
- long now = DateTime.Now.Ticks;
- _lastCheckOut = now;
- object o = null;
- lock (this)
- {
- try
- {
- foreach (DictionaryEntry myEntry in unlocked)
- {
- o = myEntry.Key;
- if (Validate(o))
- {
- unlocked.Remove(o);
- locked.Add(o, now);
- return (o);
- }
- else
- {
- unlocked.Remove(o);
- Expire(o);
- o = null;
- }
- }
- }
- catch (Exception) { }
- o = Create();
- locked.Add(o, now);
- }
- return o;
- }
- /// <summary>
- /// 清除数据库连接
- /// </summary>
- /// <param name="o"></param>
- internal void ReturnObjectToPool(object o)
- {
- if (o != null)
- {
- lock (this)
- {
- locked.Remove(o);
- unlocked.Add(o, DateTime.Now.Ticks);
- }
- }
- }
- }
- }
3.2 DBConnectionSingleton类 - 数据库连接池(实现了ObjectPool类的Create,Validate,Expire方法,并使用了单例模式)
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Data.SqlClient;
- namespace SqlPool
- {
- class DBConnectionSingleton:ObjectPool
- {
- private DBConnectionSingleton() { }
- /// <summary>
- /// 以单例模式创建数据库连接池
- /// </summary>
- public static readonly DBConnectionSingleton Instance = new DBConnectionSingleton();
- private static string _connectionString = @"Data Source=192.168.168.251/Sql2005;Initial Catalog=XX;User ID=sa;Password=777";
- /// <summary>
- /// 数据库连接字符串
- /// </summary>
- public static string ConnectionString
- {
- set {
- _connectionString = value;
- }
- get
- {
- return _connectionString;
- }
- }
- /// <summary>
- /// 创建数据库连接
- /// </summary>
- /// <returns></returns>
- protected override object Create()
- {
- SqlConnection temp = new SqlConnection(_connectionString);
- temp.Open();
- return temp;
- }
- /// <summary>
- /// 判断DB是否已连接
- /// </summary>
- /// <param name="o"></param>
- /// <returns></returns>
- protected override bool Validate(object o)
- {
- try
- {
- SqlConnection temp = (SqlConnection)o;
- return (!((temp.State.Equals(System.Data.ConnectionState.Closed))));
- }
- catch
- {
- return false;
- }
- }
- /// <summary>
- /// 关闭DB连接
- /// </summary>
- /// <param name="o"></param>
- protected override void Expire(object o)
- {
- try
- {
- ((SqlConnection)o).Close();
- }
- catch {
- }
- }
- /// <summary>
- /// 获得DB连接
- /// </summary>
- /// <returns></returns>
- public SqlConnection BorrowDBConnection()
- {
- try
- {
- return ((SqlConnection)base.GetObjectFromPool());
- }
- catch(Exception e) {
- throw e;
- }
- }
- /// <summary>
- /// 清除DB连接
- /// </summary>
- /// <param name="e"></param>
- public void ReturnDBConnecion(SqlConnection e)
- {
- base.ReturnObjectToPool(e);
- }
- }
- }
3.3 Main函数
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Data.SqlClient;
- namespace SqlPool
- {
- class Program
- {
- static void Main(string[] args)
- {
- DBConnectionSingleton pool;
- //获得数据库连接池的单例模式。
- pool = DBConnectionSingleton.Instance;
- DBConnectionSingleton.ConnectionString = @"Data Source=192.168.168.251/Sql2005;Initial Catalog=XX;User ID=sa;Password=777";
- SqlConnection myConnection = pool.BorrowDBConnection();
- pool.ReturnDBConnecion(myConnection);
- System.Threading.Thread.Sleep(5000);
- }
- }
- }
4 多线程应用:数据库连接池相关推荐
- Flask和mysql多线程_数据库连接池Flask-SQLAlchemy中多线程安全的问题
使用flask-sqlalchemy写代码码到一半,突然想到,Session是否是线程安全的?于是上官方文档,答案是否! 那问题来了,怎么破?因为它会牵涉到多线程情况下,调用rollback导致的不可 ...
- 【Python SQLAlchemy】数据库连接池SQLAlchemy中多线程安全的问题
问题描述 写了一个apscheduler定时任务 里面用到SQLAlchemy在同一时间点开启了18个任务,用于更新18个表 但是最终看数据库表的时候,发现有2个表未更新.查看打印日志均正常,查找原因 ...
- Python爬取股票数据存入mysql数据库,获取股票(最新、最高、今开、成交量、成交额、量比、换手率、涨幅等)支持多线程+数据库连接池
项目简介 (Python)爬虫 + MySQL + Redis项目. 爬取下来的数据可用于后续的数据分析(我计划将其用于我的毕业设计). 未来会将数据分析的可视化部署到服务器上, 并添加股票降价通知的 ...
- python多线程并发访问数据库连接池原理以及代码
现状 在工作中难免会使用数据库,为了能够高效并发访问数据库,数据库连接池必不可少,由于本站copy模式盛行,导致数据库连接池被错误使用,遇到错误甚至追求能跑通就行. 本文就python版本的数据库链接 ...
- mysql 连接池 多线程_4 多线程应用:数据库连接池 | 学步园
首先说明一下:这个例子是来源于[C#线程参考手册]参考手册内的一个例子,在这个我只是想研究一下她的设计原理. 具体好用不好用,因为没有做具体项目的测试,所以提醒大家注意. 1 设计思路: 1.1 在程 ...
- 聊一个不常见的面试题:为什么数据库连接池不采用 IO 多路复用?
欢迎关注方志朋的博客,回复"666"获面试宝典 今天我们聊一个不常见的 Java 面试题:为什么数据库连接池不采用 IO 多路复用? 这是一个非常好的问题.IO多路复用被视为是非常 ...
- 为什么数据库连接池不采用 IO 多路复用?
欢迎关注方志朋的博客,回复"666"获面试宝典 接着,今天我们聊一个不常见的 Java 面试题:为什么数据库连接池不采用 IO 多路复用? 这是一个非常好的问题.IO多路复用被视为 ...
- 数据库连接池为什么要用threadlocal呢?不用会怎样?
点击关注公众号,Java干货及时送达 来源:blog.csdn.net/qq_42405666/article/details/108258820 这个问题我疑问了很久很久,主要如下截图. 个连接对应 ...
- 数据库连接池到底应该设多大?
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:kelgon www.jianshu.com/p/a8f65 ...
最新文章
- TMS320F28335项目开发记录2_CCS与JTAG仿真器连接问题汇总
- CV04-UNet笔记
- DL之AlexNet:利用卷积神经网络类AlexNet实现猫狗分类识别(图片数据增强→保存h5模型)
- YbtOJ-森林之和【dp】
- 前端常见的加密算法介绍
- 比特飞解决方案大汇总,你的贴身家教
- Android 系统性能优化(41)---Android代码内存优化建议-OnTrimMemory优化
- 2022年中国商业十大热点展望:共同富裕、碳达峰碳中和、创新、数字化、新国货.........
- 可变cell,自适应cell,理解iOS 8中的Self Sizing Cells和Dynamic Type
- JavaWeb开发必会技巧1——导入jar包
- BZOJ2330:[SCOI2011]糖果(差分约束)
- 立体栅格地图_三维栅格地图构建之三:点集到栅格的投射
- 【python 监控报警】python自动发钉钉机器人报警
- linux服务器双网卡配置,linux 关于主机服务器双网卡bond配置
- 批量下载网页链接---数据集批量下载
- EXCEL文本函数-数字小写换大写-英文大小写互换
- android动态mac地址,android 设备唯一码的获取,Cpu号,Mac地址
- 破解魔术的秘密(一)——直面秘密的角落
- java excel 判断组重复_Java判断Excel某列是否有重复值
- 实战智能推荐系统(5)-- 推荐系统评价指标
热门文章
- java批量下载图片_Java批量写入文件和下载图片的示例代码
- 基于ESP32学习MicroPython(三): 流水灯案例
- IPV4 IPV6 DHCP中继服务器之思科交换机配置
- 戴尔Inspiron 灵越 14R(N4120)加装固态硬盘
- GeneXus学习记录——创建KB(KnowledgeBase/知识库)
- dpi 、 dip 、分辨率、屏幕尺寸、px、density 关系以及换算
- java empty_Java Optional empty()用法及代码示例
- 齐枭飞 Vue系列--vue的图片路径,和背景图片路径打包后错误解决
- 黑马程序员——Java字符流、字节流IO流
- [转]数码照片的JPG文件高级信息(用C#读取图片的EXIF信息)