mysql数据库连接池 手动编写
源码来源于http://www.toutiao.com/a6350448676050174209/,留存以供以后参考学习
先上一张项目托普图
然后分别列出各个文件的源码:
MyPool.java(就是个接口)
package com.audi; public interface MyPool { PoolConnection getConnection(); void createConnections(int count); }
MyPoolImpl.java(接口的实现类)
package com.audi; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; import java.util.Vector; import com.mysql.jdbc.Driver; public class MyPoolImpl implements MyPool { private static String jdbcDriver = ""; private static String jdbcUrl = ""; private static String userName = ""; private static String password = ""; private static int initCount; private static int stepSize; private static int poolMaxSize; private static Vector<PoolConnection> poolConnections = new Vector<PoolConnection>(); public MyPoolImpl() { // TODO Auto-generated constructor stub init(); } private void init() { // TODO Auto-generated method stub // 读取配置文件 InputStream in = MyPoolImpl.class.getClassLoader() .getResourceAsStream("mysqlConnection.properties"); // InputStream inputStream = new in Properties pro = new Properties(); try { // 装载配置文件输入流 pro.load(in); } catch (Exception e) { // TODO: handle exception } // 从配置文件中读取出配置参数 jdbcDriver = pro.getProperty("jdbcDriver"); jdbcUrl = pro.getProperty("jdbcUrl"); userName = pro.getProperty("userName"); password = pro.getProperty("password"); initCount = Integer.valueOf(pro.getProperty("initCount")); stepSize = Integer.valueOf(pro.getProperty("stepSize")); poolMaxSize = Integer.valueOf(pro.getProperty("poolMaxSize")); try { // 获取驱动对象并注册 Driver driver = (Driver) Class.forName(jdbcDriver).newInstance(); DriverManager.registerDriver(driver); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } // 创建一定数量的初始链接 createConnections(initCount); } @Override public PoolConnection getConnection() { // TODO Auto-generated method stub if (poolConnections.size() <= 0) { System.out.println("链接池为空,获取数据库链接失败!!!"); throw new RuntimeException("链接池为空,获取数据库链接失败!!!"); } PoolConnection connection = getRealConnection(); // 如果没有成功的获取链接就创建一定数量的链接 并从中获取一个有效链接 while(connection == null) { createConnections(stepSize); connection = getRealConnection(); try { // 这里睡眠的原因时考虑到第一次获取链接失败,可能有多个线程在等待链接资源,所以当前线程先等待一下,避开高峰 Thread.sleep(300); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } return connection; } // 注意有synchronized关键字 private synchronized PoolConnection getRealConnection() { // TODO Auto-generated method stub for (PoolConnection conn : poolConnections) { // 如果当前链接空闲则返回该链接对象 if (!conn.isBusy()) { Connection connection = conn.getConn(); try { // 判断获得的链接是否是有效的,如果无效就创建一个新的链接 isValid方法其实就是在定时时间到的时候执行一下sql语句 if (!connection.isValid(2000)) { Connection validConn = DriverManager.getConnection(jdbcUrl, userName, password); conn.setConn(validConn); } } catch (Exception e) { // TODO: handle exception } } conn.setBusy(true); return conn; } return null; } // 创建链接 @Override public void createConnections(int count) { // TODO Auto-generated method stub if (poolMaxSize > 0 && poolConnections.size() + count > poolMaxSize) { System.out.println("创建链接对象失败,因为数据库链接数量已达上限!!"); throw new RuntimeException("创建链接对象失败,因为数据库链接数量已达上限!!"); } // 否则就开始创建链接 for (int i = 0; i < count; i++) { try { Connection conn = DriverManager.getConnection(jdbcUrl, userName, password); // 封装链接对象 并存入vecter PoolConnection poolConnection = new PoolConnection(conn, false); poolConnections.add(poolConnection); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
PoolConnection.java(里面会进行一些连接参数的配置)
package com.audi; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; public class PoolConnection { private Connection conn; private boolean isBusy = false; public Connection getConn() { return conn; } public void setConn(Connection conn) { this.conn = conn; } public boolean isBusy() { return isBusy; } public void setBusy(boolean isBusy) { this.isBusy = isBusy; } public PoolConnection(Connection conn,boolean isBusy) { this.conn = conn; this.isBusy = isBusy; } public ResultSet querySql(String sql) { ResultSet resultSet = null; Statement statement = null; try { statement = conn.createStatement(); resultSet = statement.executeQuery(sql); } catch (Exception e) { // TODO: handle exception } return resultSet; } public void close() { this.isBusy = false; } }
PoolManager.java(使用内部类的方式获取连接池对象)
package com.audi; public class PoolManager { private static class CreatePool { private static MyPoolImpl myPoolImpl= new MyPoolImpl(); } public static MyPoolImpl getInStance() { return CreatePool.myPoolImpl; } }
最后是测试类
package com.audi; import java.sql.ResultSet; public class TestPool { private static MyPoolImpl poolImpl =PoolManager.getInStance(); public static void main(String[] args) { // TODO Auto-generated method stub /*long time= System.currentTimeMillis(); for (int i = 0; i < 2000; i++) { System.out.println("第"+i+"次执行"); selecData(); } System.out.println("運行時間"+(System.currentTimeMillis()-time));*/ // System.out.println(new Date()); //selecData(); // 创建2000个数据库链接线程 long time= System.currentTimeMillis(); for (int i = 0; i < 2000; i++) { System.out.println("第"+i+"次执行"); new Thread(new Runnable() { public void run() { selecData(); } }); } System.out.println("運行時間"+(System.currentTimeMillis()-time)); } public synchronized static void selecData() { PoolConnection connection = poolImpl.getConnection(); ResultSet resultSet = connection.querySql("select * from Student"); try { while (resultSet.next()) { System.out.println(resultSet.getString("ID")+"\t"+resultSet.getString("NAME")+"\t"+resultSet.getString("AGE")); } resultSet.close(); connection.close(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } }
数据库连接参数配置文件
mysqlConnection.properties
jdbcDriver=com.mysql.jdbc.Driver jdbcUrl=jdbc\:mysql\://localhost\:3306/test userName=root password=w513723 initCount=10 stepSize=5 poolMaxSize=200