JDBC 连接池
来源:互联网 发布:列宁 知乎 编辑:程序博客网 时间:2024/05/04 00:22
1.创建jdbc配置文件 ds.config.properties
driver=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/competitionusername=rootpassword=123456maxConnection=10initialConnection=5
2.编写数据库连接池类
package com.Tool.sql;import java.io.IOException;import java.io.InputStream;import java.sql.CallableStatement;import java.sql.Connection;import java.sql.DatabaseMetaData;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.Iterator;import java.util.LinkedList;import java.util.Properties;public class ConnectionPool { private String dbDriver = ""; //数据库驱动 private String dbUrl = ""; //数据URL private String dbUsername = ""; //数据库用户名 private String dbPassword = ""; //数据库用户密码 private String testTable = ""; //测试连接是否可用的测试表名,默认没有测试表 private int initialConnection = 0; //连接池的初始大小// private int incrementalConnection = 0; //连接池自动增加的大小 private int maxConnections = 0; //连接池的最大的大小 private int inUsedConnection = 0; //已使用的连接数 static private long m_lastClearClosedConnection = System.currentTimeMillis(); private static long CHECK_CLOSED_CONNECTION_TIME = 3 * 60 * 60 * 1000/*250*/; //3 hours //使用LinkedList集合来存放数据库链接, private static LinkedList<Connection> listConnections = new LinkedList<Connection>(); private static ConnectionPool connectionPool = new ConnectionPool(); /** * 构造函数 * 功能:获取数据库配置文件数据, * 并创建初始数量大小的数据库连接放在连接池中 */ private ConnectionPool() { InputStream in = JdbcConnectionPool.class.getClassLoader().getResourceAsStream("ds.config.properties"); Properties prop = new Properties(); try { prop.load(in); } catch (IOException e) { e.printStackTrace(); } dbDriver = prop.getProperty("driver"); dbUrl = prop.getProperty("url"); dbUsername = prop.getProperty("username"); dbPassword = prop.getProperty("password"); initialConnection = Integer.parseInt(prop.getProperty("initialConnection")); maxConnections = Integer.parseInt(prop.getProperty("maxConnection")); initConnectionPool(); } //单例 public static ConnectionPool getIntense(){ return connectionPool; } /** * 作者:LinHaiZhen * 时间:2016-3-31 下午08:14:56 * 函数名:initConnectionPool * 功能:初始化数据库连接池listConnections * 参数: * 返回值:void */ private void initConnectionPool(){ try { //加载数据库驱动 Class.forName(dbDriver); for(int i=0; i<initialConnection; i++){ Connection conn = newConnection();// System.out.println("获取到了连接---" + conn); //将获取到的数据库连接加入到listConnections集合中, //listConnections集合此时就是一个存放了数据库连接的连接池 listConnections.add(conn); } } catch (Exception e) { e.printStackTrace(); } } /** * 作者:LinHaiZhen * 时间:2016-3-31 下午07:26:08 * 函数名:getConnection * 功能:得到连接 * 参数:@return * 返回值:Connection * @throws SQLException */ public synchronized Connection getConnection() throws SQLException{ clearClosedConnection(); if(listConnections == null){ System.out.println("连接池没创建"); throw new SQLException("连接池没创建"); } Connection conn = null; // 1.获得一个可用的数据库连接 conn = getFreeConnection(); // 2.如果连接为空,等待一会,重新再试 if(conn == null){ wait(5000); //等待5秒 conn = getFreeConnection(); // 重新再试 if(conn == null){ throw new SQLException("连接超时,没有可用连接"); } }// while(conn == null){// wait(250); //等待250毫秒// conn = getFreeConnection(); // 重新再试// } //3.如果获得可用连接,使用连接数量变量加1 if(conn != null){ inUsedConnection++; System.out.println("现有" +inUsedConnection+ "个连接在使用"); System.out.println("数据库连接池大小是---" + listConnections.size()); } return conn; } /** * 作者:LinHaiZhen * 时间:2016-4-1 下午06:00:38 * 函数名:getFreeConnection * 功能:得到可用的连接 * 参数:@return * 返回值:Connection */ private Connection getFreeConnection(){ Connection conn = null; //如果数据库连接池中有连接对象,取出连接返回 if(listConnections.size() > 0){ //从connections集合中获取一个数据库连接,并删除数据库中的这个连接 conn = listConnections.removeFirst(); }else{ //1.如果已创建连接数已达到数据库最大连接数 if(inUsedConnection>=maxConnections){ conn = null; }else{ //2.否则,新建连接 conn = newConnection(); } } return conn; } /** * 作者:LinHaiZhen * 时间:2016-4-2 下午06:41:09 * 函数名:returnConnection * 功能:用完,返回连接,放回到连接池中 * 参数:@param conn * 参数:@param st * 参数:@param rs * 返回值:void */ public synchronized void returnConnection(Connection con,PreparedStatement ps,ResultSet res){ //1.确保连接池存在,如果连接池不存在,则关闭相关连接,然后直接返回 if(listConnections == null){ System.out.println("连接池不存在,无法返回到此连接池中!");// throw new MyException("连接池不存在,无法返回到此连接池中!"); if(con != null){ closeConnection(con); } try { if(ps != null){ ps.close(); } if(res != null){ res.close(); } } catch (SQLException e) { e.printStackTrace(); } return; } //2.将连接返回到连接池中并关闭相关连接 listConnections.add(con); try { if(ps != null){ ps.close(); } if(res != null){ res.close(); } } catch (SQLException e) { e.printStackTrace(); } inUsedConnection--; System.out.println("返回连接"); } /** * 作者:LinHaiZhen * 时间:2016-4-4 下午06:00:20 * 函数名:returnConnection * 功能:用完,返回连接,放回到连接池中 * 参数:@param con * 参数:@param cs * 参数:@param res * 返回值:void */ public synchronized void returnConnection(Connection con,CallableStatement cs,ResultSet res){ //1.确保连接池存在,如果连接池不存在,则关闭相关连接,然后直接返回 if(listConnections == null){ System.out.println("连接池不存在,无法返回到此连接池中!");// throw new MyException("连接池不存在,无法返回到此连接池中!"); if(con != null){ closeConnection(con); } try { if(cs != null){ cs.close(); } if(res != null){ res.close(); } } catch (SQLException e) { e.printStackTrace(); } return; } //2.将连接返回到连接池中并关闭相关连接 listConnections.add(con); try { if(cs != null){ cs.close(); } if(res != null){ res.close(); } } catch (SQLException e) { e.printStackTrace(); } inUsedConnection--; System.out.println("返回连接"); } /** * 作者:LinHaiZhen * 时间:2016-4-4 下午05:52:35 * 函数名:用完,返回连接,放回到连接池中 * 功能:TODO * 参数:@param conn * 参数:@param st * 返回值:void */ public synchronized void returnConnection(Connection conn,PreparedStatement st){ //1.确保连接池存在,如果连接池不存在,则关闭相关连接,然后直接返回 if(listConnections == null){ System.out.println("连接池不存在,无法返回到此连接池中!");// throw new MyException("连接池不存在,无法返回到此连接池中!"); if(conn != null){ closeConnection(conn); } try { if(st != null){ st.close(); } } catch (SQLException e) { e.printStackTrace(); } return; } //2.将连接返回到连接池中并关闭相关连接 listConnections.add(conn); try { if(st != null){ st.close(); } } catch (SQLException e) { e.printStackTrace(); } inUsedConnection--; System.out.println("返回连接"); } /** * 作者:LinHaiZhen * 时间:2016-3-31 下午08:51:57 * 函数名:returnConnection * 功能:用完,返回连接,放回到连接池中 * 参数:@param conn * 返回值:void */ public synchronized void returnConnection(Connection conn){ //1.确保连接池存在,如果连接池不存在,则关闭相关连接,然后直接返回 if(listConnections == null){ System.out.println("连接池不存在,无法返回到此连接池中!");// throw new MyException("连接池不存在,无法返回到此连接池中!"); if(conn != null){ closeConnection(conn); } return; } //2.将连接返回到连接池中并关闭相关连接 listConnections.add(conn); inUsedConnection--; System.out.println("返回连接"); } /** * 作者:LinHaiZhen * 时间:2016-3-31 下午03:06:10 * 函数名:newConnection * 功能:创建一个新的数据库连接并返回 * 参数:@return * 参数:@throws SQLException * 返回值:Connection */ private Connection newConnection(){ //创建一个数据库连接 Connection conn = null; try { conn = DriverManager.getConnection(dbUrl, dbUsername, dbPassword);// System.out.println("创建连接"); //如果是第一次创建连接,检查数据库,获得此数据库允许支持的最大客户连接数目 //connections.size()==0&&inUsedConnection==0表示目前没有连接已被创建 if(listConnections.size()==0 && inUsedConnection==0){ DatabaseMetaData metaData = conn.getMetaData(); int driverMaxConnections = metaData.getMaxConnections(); //数据库返回的driverMaxConnection若为0,表示此数据库没有最大连接限制 //或数据库的最大连接限制不知道 //driverMaxConnection为返回的一个整数,表示此数据库允许客户连接的数目 //如果连接池中设置的最大连接数量大于数据库允许的连接数目,则连接池的最大 //连接数目为数据库允许的最大数目 if(driverMaxConnections>0 && this.maxConnections>driverMaxConnections){ this.maxConnections = driverMaxConnections; } } } catch (SQLException e) { e.printStackTrace(); } return conn; } /** * 作者:LinHaiZhen * 时间:2016-3-31 下午10:20:00 * 函数名:releaseConnection * 功能:释放所有连接 * 参数: * 返回值:void */ public synchronized void releaseConnection(){ Iterator allConns = listConnections.iterator(); while(allConns.hasNext()){ Connection conn = (Connection) allConns.next(); try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } listConnections.clear(); } /** * 作者:LinHaiZhen * 时间:2016-4-1 下午04:26:12 * 函数名:closeConnection * 功能:关闭一个数据库连接 * 参数:@param conn * 返回值:void */ private void closeConnection(Connection conn){ try { conn.close(); } catch (SQLException e) { System.out.println("关闭数据库连接出错" + e.getMessage()); } } /** * 作者:LinHaiZhen * 时间:2016-4-1 下午04:30:15 * 函数名:testConnection * 功能:测试连接是否可用 * 参数:@param conn * 参数:@return * 返回值:boolean */ private boolean testConnection(Connection conn){ try { //判断测试表是否存在 if(testTable.equals("")){ conn.setAutoCommit(true); }else{ Statement stmt = conn.createStatement(); stmt.execute("select count(*) from " + testTable); } } catch (SQLException e) { closeConnection(conn); return false; } return true; } /** * 作者:LinHaiZhen * 时间:2016-4-1 下午04:31:15 * 函数名:wait * 功能:使程序等待给定的毫秒数 * 参数:@param mSeconds * 返回值:void */ private void wait(int mSeconds){ try { Thread.sleep(mSeconds); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 作者:LinHaiZhen * 时间:2016-4-2 下午03:18:18 * 函数名:clearClosedConnection * 功能:关闭多余的连接 * 参数: * 返回值:void */ private void clearClosedConnection(){ long time = System.currentTimeMillis(); //1.时间不合理,没有必要检查 if(time < m_lastClearClosedConnection){ time = m_lastClearClosedConnection; return; } //2.时间太短,没有必要检查 if(time - m_lastClearClosedConnection < CHECK_CLOSED_CONNECTION_TIME){ return; } m_lastClearClosedConnection = time; //3.开始检测连接池中是否有已关闭的连接 Iterator iterator = listConnections.iterator(); while(iterator.hasNext()){ Connection conn = (Connection) iterator.next(); try { if(conn.isClosed()){ iterator.remove(); } } catch (SQLException e) { iterator.remove(); e.printStackTrace(); } } //4.清除多余的Connection int decrease = getDecreasingConnectionCount(); while (decrease > 0 && listConnections.size() > 0) { Connection conn = listConnections.removeFirst(); closeConnection(conn); decrease--; } } /** * 作者:LinHaiZhen * 时间:2016-4-2 下午03:16:00 * 函数名:getDecreasingConnectionCount * 功能:得到需要减少的连接数 * 参数:@return * 返回值:int */ private int getDecreasingConnectionCount(){ int count = 0; int current = listConnections.size() + inUsedConnection; if(current > initialConnection){ count = current-initialConnection; } return count; }}
3.用法
package com.Tool.sql;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;public class test implements Runnable{ ConnectionPool pool = ConnectionPool.getIntense(); public static void main(String[] args) { test test1 = new test(); for(int i=0; i<100; i++){ Thread a = new Thread(test1, "线程"+i); a.start(); } } @Override public void run() { String sql = "select * from user where UserId = 62"; ResultSet rs = null; PreparedStatement statement = null; Connection conn = null; try { conn = pool.getConnection(); statement = conn.prepareStatement(sql); rs = statement.executeQuery(sql); while(rs.next()){ System.out.println(Thread.currentThread().getName() + "--->" + "id:" + rs.getInt("UserId")+ "用户名" + rs.getString("UserName")); } }catch (SQLException e) { e.printStackTrace(); }finally{ pool.returnConnection(conn,statement,rs); } }}
0 0
- JDBC连接池
- Jdbc连接池介绍
- JDBC与连接池
- JDBC与连接池
- Jdbc连接池介绍
- JDBC连接池实现
- jdbc连接池
- jdbc连接池
- JDBC+MySQL连接池
- jdbc连接池
- JDBC 连接池代码
- JDBC之连接池
- JDBC之连接池
- JDBC 连接池
- jdbc连接池实现
- jdbc连接池
- jdbc连接池总结
- Spring2 JDBC 连接池
- 示例:排序算法
- 在spring MVC的配置文件中添加freemarker的支持
- Qt QWidget实现手势缩放和平移(一)
- synchronized同步问题完美用法
- kubernetes 1.5 集群安装
- JDBC 连接池
- kookie操作API
- javaWeb 各类资源和页面的地址和路径的写法。
- Java 操作按照尺寸裁剪图片
- Android 带文字的进度条,文字颜色随进度条的增加而渐变的效果
- Ubuntu 出现apt-get: Package has no installation candidate问题
- Android 获取手机唯一标识 IMEI号 应用名称、版本名、版本号
- 2121. 【2016-12-31普及组模拟】简单游戏
- DNS域名解析详解