// 后面贴上源码
之前写一个小工具,发现了一个问题,发现部署到云计算上面,由于需要操作其他环境的数据库,发现获取66 175环境的获取连接非常缓慢。
通过打印日志,然后部署到服务器,发现获取175环境的数据库连接池居然要6s?? 获取66环境需要3s 显然不合理?
一个查询居然要5-6秒,具体原因我真的不懂,为啥175连的那么困难? 是不是物理机隔得太远了?还是啥。。 反正想着既然这样,
本来想用业界成熟的c3p0,或者本平台已经在使用的阿里巴巴druid连接池,但是好像不太符合我们的需求。因为我们需要保存很多个不同环境的连接,数据结构不能是List单纯保存连接,需要一个map映射。
最后自己写一个自定义连接池吧。。。 把获取到的连接保存到集合里,不需要就放回去,需要在拿回来,这是最简单的思路,就开始编码了,看看能不能解决问题。
思路大概这样吧:
注意要给释放连接和获取连接加上重入锁,保证多线程的可靠性。
最后从新部署测试。
----------遗留问题,一直不明白为什么jdbc建立connection连接 对于66环境和175环境需要3-5s, 而其他环境建立连接就算不用连接池只需要几ms。
最后附上代码
package com.huawei.solution.utils; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; import static com.huawei.solution.constants.CommonConstants.PASS_WORD; import static com.huawei.solution.constants.CommonConstants.USER_NAME; import static com.huawei.solution.constants.CommonConstants.DRIVER_CLASS_NAME; /** * @ClassNme DataSourcePoolNew * @Author x84104122 * @Date 2018/10/29 17:45 * @Description 自定义简单数据库映射连接池 */ public class DataSourcePoolNew { /** * 最大连接数 */ private static final int COUNT = 10; /** * 存放数据库 * key 为环境 value 为数据库 */ public static final Map<Integer, LinkedList<Connection>> connections = new ConcurrentHashMap<>(); /** * 创建锁 */ private static final ReentrantLock lock = new ReentrantLock(); private static final Condition notEmpty = lock.newCondition(); private static final Condition notFull = lock.newCondition(); /** * 数据库连接 */ private static String URL; public DataSourcePoolNew() { } /** * 初始化信息 */ public DataSourcePoolNew(Integer key,String url) { final ReentrantLock reentrantLock = lock; reentrantLock.lock(); try { //加载驱动 URL = url; Class.forName(DRIVER_CLASS_NAME); LinkedList<Connection> connectionList = new LinkedList<>(); for (int i = 0; i < COUNT; i++) { Connection connection = DriverManager.getConnection(URL, USER_NAME, PASS_WORD); connectionList.add(connection); } connections.put(key, connectionList); } catch (Exception e) { e.printStackTrace(); } finally { reentrantLock.unlock(); } } /** * 获取Connection */ public Connection getConnection(Integer key) { if (!connections.containsKey(key)){ return null; } final ReentrantLock reentrantLock = lock; reentrantLock.lock(); try { //如果没有连接了,则等待着新放入的连接 if (connections.get(key).isEmpty()) { notEmpty.await(); } Connection connection = connections.get(key).removeFirst(); notFull.signalAll(); return connection; } catch (InterruptedException e) { e.printStackTrace(); } finally { reentrantLock.unlock(); } return null; } /** * 释放连接 * * @param connection */ public static void release(Integer key, Connection connection) { if (!connections.containsKey(key)){ return ; } final ReentrantLock reentrantLock = lock; reentrantLock.lock(); try { if (connections.get(key).size() == COUNT) { notFull.await(); } if (connection == null || connection.isClosed()) { connections.get(key).add(DriverManager.getConnection(URL, USER_NAME, PASS_WORD)); notEmpty.signalAll(); return; } //恢复默认值 if (connection.getAutoCommit() == false) { connection.setAutoCommit(true); } connections.get(key).add(connection); notEmpty.signalAll(); } catch (InterruptedException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { reentrantLock.unlock(); } } }
使用Demo
获取连接
if (DataSourcePoolNew.connections.containsKey(environment) && !DataSourcePoolNew.connections.get(environment).isEmpty()) { con = DataSourcePoolNew.connections.get(environment).removeFirst(); } else { con = new DataSourcePoolNew(environment, url).getConnection(environment); }
释放连接
放回集合了
DataSourcePoolNew.release(environment, con);
本文主要给大家提供一个思路,深入理解连接池。大家可以自己自定义自己想要的数据结构模型,去获取相应的数据库连接池。代码是活的,思路是死的。