1. 资源重用
当多个用户频繁的去对数据库进行读写 *** 作时,会不间断的创建Connection,在数据库开始读写数据之前,把资源过多的分配给创建连接释放连接上,这笔开销得不偿失.数据库连接池的对连接Connection的资源回收机制对此做出了优化
2. 更快的系统响应速度
数据库连接池一旦初始化,用户获取的Connection不再创建新的,而是从现有的容器里面取,使得直接利用成为可能,避免了数据库连接初始化和释放过程的时间开销,从而缩减了系统整体响应时间。
3. 新的资源分配手段
对于多应用共享同一数据库的系统而言,某一应用最大可用数据库连接数的限制,避免某一应用独占所有数据库资源。
4. 统一的连接管理,避免数据库连接泄漏
数据库连接池提供连接超时设定,超时后会重试,针对用户获取到的不健康的Connection,同样会重新分配新的连接,从而避免了常规数据库连接 *** 作中可能出现的资源泄漏
实现一个简单的数据库连接池目标:
要实现的数据库连接池,统一注册驱动(替换每一次连接数据库都要注册驱动的时代)用户想对数据库进行进一步的 *** 作,需要在数据库连接池中获取连接Connection用户对队数据库读写完毕之后,连接池回收当前的Connection两个容器
数据库连接池 = 空闲连接池 + 工作连接池
三个重要的参数
最大连接数最大连接数是对Connection总数的限制 一般是((核心数 * 2) + 有效磁盘数)空闲连接数空闲连接数 表示当前的空闲连接池中的Connection的数量,我们给他规定最大值和最小值当前值 < 最大连接数 表示用户有机会获取连接如果 空闲连接池的size>0 直接获取连接否则 创建一个新的Connection给用户当前值 >= 最大连接数 Connection的创建达到了上限,用户只能等待重试工作连接数工作连接数 表示 当前工作连接池中的Connection的数量获取连接经历什么?
空闲连接池中的d出一个Connection把当前的Connection加入到工作连接池连接是如何被回收的?
如果空闲连接池未满.直接添加进去把工作连接池中相应的连接移除如果空闲连接池满了.直接close()掉把工作连接池中相应的连接移除配置文件读取工具类public class propertIEsUtil { private static PropertIEs configObj = new PropertIEs(); static{ // 使用类加载器读取的文件要放在src下 inputStream connectionPool = Thread.currentThread().getContextClassLoader().getResourceAsstream("pool.propertIEs"); inputStreamReader inputStreamReader = new inputStreamReader(connectionPool); try { configObj.load(inputStreamReader); } catch (IOException e) { e.printstacktrace(); } } public static String getValue(String key){ return configObj.getProperty(key); }}
定义接口,规范我们的连接池的方法public interface myConnectionPool { /** * 获取连接 * @return */ public Connection getConnection(); /** * 释放连接 * @param connection */ public voID releaseConnection(Connection connection);}
具体的实现类实现myConnectionPool接口public class ConnectionPool implements IConnection { // 线程安全的两个容器,分别存放空闲线程数和活动的线程数 private @R_301_6818@<Connection> freeConnection = new copyOnWriteArray@R_301_6818@<>(); private @R_301_6818@<Connection> activeConnection = new copyOnWriteArray@R_301_6818@<>(); // 原子类 标记的是 空闲池的存放的连接数 private AtomicInteger atomicInteger; public ConnectionPool() { this.atomicInteger = new AtomicInteger(0); // 初始化空闲连接池 init(); } // 初始空闲连接池 public voID init() { // 获取连接数,给freeConnection 池添加指定数量的连接数 for (int i = 0; i < Integer.valueOf(propertIEsUtil.getValue("initConnections")); i++) { // 创建连接 Connection connection = newConnection(); if (null != connection) { // 添加到容器 freeConnection.add(connection); } } } // 获取连接 @OverrIDe public synchronized Connection getConnection() { Connection connection=null; // 判断是否达到了最大连接数--> 决定给用户连接还是让他等待 if (atomicInteger.get()<Integer.valueOf(propertIEsUtil.getValue("maxActiveConnetions"))){ // 当前小于最大的连接数,直接给当前的用户连接 if (freeConnection.size()>0){ // 空闲线程里面有直接从空闲线程里面取 connection = freeConnection.remove(0); }else{ // 空闲线程里面没有,直接创建一个新的连接 connection = newConnection(); } // 判断连接是否可用 if(isAvailable(connection)){ // 添加到一个活动线程里面 activeConnection.add(connection); }else{ // 如果连接不可用,递归 // 如果连接不可用的话,说明有一次newConnection()失败了,我们得 atomicInteger.decrementAndGet(); 把newConnection()里面的原子增加去掉 atomicInteger.decrementAndGet(); connection = getConnection(); } }else{ // 等待 try { wait(Integer.valueOf(propertIEsUtil.getValue("connTimeOut"))); } catch (InterruptedException e) { e.printstacktrace(); } } return connection; } // 释放本次连接 ; 把本次连接从活动池 转移到 空闲池 @OverrIDe public synchronized voID releaseConnection(Connection connection) { // 判断连接是否可用 if(isAvailable(connection)){ // 可用 // 回收 // 判断空闲池是否满了 if(freeConnection.size()<Integer.valueOf(propertIEsUtil.getValue("maxConnections"))){ // 未满 freeConnection.add(connection); }else{ // 满了 try { connection.close(); } catch (sqlException e) { e.printstacktrace(); } } // 移除出去当前的这个连接 activeConnection.remove(connection); atomicInteger.decrementAndGet(); // 现在可能有连接正在等待,既然这里释放了,那么就唤醒全部等待的线程 notifyAll(); }else{ // 不可用 throw new RuntimeException("连接回收异常"); } } // 创建新的连接 public Connection newConnection() { try { // 注册驱动 Class.forname(propertIEsUtil.getValue("drivername")); // 获取连接 Connection connection = DriverManager.getConnection( propertIEsUtil.getValue("url"),propertIEsUtil.getValue("username"),propertIEsUtil.getValue("password")); // 原子增加 atomicInteger.addAndGet(1); return connection; } catch (Exception e) { e.printstacktrace(); return null; } } // 判断连接是否可用 public boolean isAvailable(Connection connection){ try { if (null==connection||connection.isClosed()){ return false; } } catch (sqlException e) { e.printstacktrace(); } return true; }}
配置文件# 数据库相关drivername=com.MysqL.jdbc.Driverurl=jdbc:MysqL://localhost:3306/textusername=rootpassword=root# 空闲池的 最小数minConnections=1# 空闲池的 最大数maxConnections=10# 初始化的连接数initConnections=5# 本次连接超时时间(重试时间)connTimeOut=1000# 最大的连接数maxActiveConnetions=10
总结 以上是内存溢出为你收集整理的实现一个简易的数据库连接池全部内容,希望文章能够帮你解决实现一个简易的数据库连接池所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)