Java技术栈 —— 手写Java数据库连接池
- 一、连接池的作用
- 二、讲解
- 1.1 类图结构
- 1.2 ConnectionPoolManager
- 1.3 DataSourceConfig
- 1.4 ConnectionPool与IConnectionPool
- 1.5 ConnEntry
- 三、收获
- 3.1 CopyOnWriteArrayList累的使用(对本文代码的一点建议和指正)
- 3.2 AtomicInteger类的使用
- 3.3 Java定时任务
一、连接池的作用
- 资源重用
- 更快的系统响应速度
- 新的资源分配手段
- 统一的连接管理,避免数据库连接泄露
一、参考文章或视频链接 |
---|
本文代码来源:[1] 《Java手写系列》-纯手写数据库连接池 |
本文代码的CSDN下载地址 - 0积分 |
[2] 《尝试手写一个框架(三)如何自己手写一套数据库连接池?》 |
[3] 《Java手写实现Mysql连接池》 |
[4] 《基于JAVA源代码生成PlantUML类图》 |
[5] 首先在Ubuntu下安装graphviz |
[6] 在IDEA中配置dot的可执行位置 |
[7] 讲的很好 UML类图关系 - 稀土掘金 |
[8] 使用UMLDoclet和PlantUML从源码生成UML类图 |
二、讲解
1.1 类图结构
本图由IDEA中的PlantUML插件生成。
1.2 ConnectionPoolManager
我认为这实际上是一个工厂类。通过这个类,User可以不关注获取细节,直接进行getConnection()操作。
1.3 DataSourceConfig
连接池配置信息类,读取配置信息。
1.4 ConnectionPool与IConnectionPool
ConnectionPool是连接池对象本身,IConnectionPool是,与ConnectionPoolManager构成关联关系。
1.5 ConnEntry
将Connection与创建时间time,组成一个Entry对,我这里对参考文章里的名字做了修改,我觉得这样的命名更贴切。
三、收获
3.1 CopyOnWriteArrayList累的使用(对本文代码的一点建议和指正)
对于
freeConns
与useConns
,作者是用CopyOnWriteArrayList对他们进行存放的,这个类保证了线程的安全性,不会出现多个线程竞争的资源安全性问题。但是我认为作者明显有点过度设计了,他的很多方法如ConnectionPool.createConn
,ConnectionPool.getPoolEntry
已经加了synchronized
关键字,就没必要再对freeConns
、useConns
这些再包装一层CopyOnWriteArrayList了,但是我打包的代码还是带了,您可以自行改为ArrayList
。ArrayList<ConnEntry> useConns = new ArrayList<ConnEntry> (); //泛型到字节码层面会有一个泛型消除的概念,请知悉 ArrayList<Connection> freeConns = new ArrayList<Connection> ();
通常,CopyOnWriteArrayList的使用场景是:存在多个线程同时进行读写操作,且读多写少,这样CopyOnWriteArrayList可以提供更好的并发性能。
3.2 AtomicInteger类的使用
我写过一篇文章,讨论过AtomicBoolean
类,Atomicxx
属于并发包中的原子操作类,并且能保证线程之间的资源可见性,CSDN会吞微信公众号链接,我把url也直接放出来,有Worker
线程类与连接池ConnectionPool
类同时对其进行读写的需求,这里的AtomicInteger
类倒不算过度使用。
3.2 参考文章或视频链接 |
---|
[1] 《竹花代码》- 李论实践公众号https://mp.weixin.qq.com/s?__biz=Mzg5ODU3Nzc0MA==&mid=2247483998&idx=1&sn=3654fc3e2d047f14e322a5007d5d5a02&chksm=c061267df716af6bacab2e1c53cd685f41012562791bd90fd7cb1ac7d20996fda4d9a2612d6b&token=1372824197&lang=zh_CN#rd |
3.3 Java定时任务
这个项目的一个收获就是掌握了如何使用Java的定时任务,实现一个
Worker
类继承TimeTask(TimeTask implements Runnable)
,那么Worker
类就是一个线程类,实现了对应的run
方法后,就可以实现在main线程以外运行,对连接池情况进行监听,然后再用java.util.Timer().schedule()
方法,对Worker
类实现定时调度,那么对连接池的定时扫描就做好了,这样就可以关闭超时未释放的连接归还到连接池中。
值得一提的是,很多心跳线程也是用这种方式实现的。[1]
一、参考文章或视频链接 |
---|
本文代码来源:[1] Java’s Heartbeat Functionality |
全文完。