一.连接池的结构设计
二.数据库配置
1.数据库配置文件
config_db.properties文件放到src下,如下:
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/framwork?useUnicode=true&characterEncoding=UTF-8 username=root password=123 poolsize=20 autocommite=true
package com.myframework.db; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Properties; /** * 用于读取配置文件 * @author xiajie * */ public class DBConfig { public static int MAX_POOL_SIZE = 20; public static String URL=""; public static String DRIVER=""; public static String USERNAME = ""; public static String PASSWORD = ""; //是否自动提交 public static boolean AUTOCOMMIT = true; static{ //读取配置文件 Properties properties = new Properties(); //获取本src文件夹所在的物理的位置(即编译后bin文件夹的绝对路径,在服务器端也可以) ///D:/WorkSpace-ALL/taotao-workspace/FrameworkByMe/bin/ String path = DBConfig.class.getResource("/").getPath(); try { properties.load(new FileInputStream(path+"config_db.properties")); URL = (String)properties.getProperty("url"); DRIVER = (String)properties.getProperty("driver"); USERNAME = (String)properties.getProperty("username"); PASSWORD = (String)properties.getProperty("password"); MAX_POOL_SIZE = Integer.parseInt(properties.getProperty("poolsize")); AUTOCOMMIT = Boolean.parseBoolean(properties.getProperty("autocommite")); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
package com.myframework.db; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; /** * 用于管理数据库连接 * @author xiajie * */ public class DBManager { /** * 用于初始化数据库连接池 */ public static void initDBPool(){ try { Class.forName(DBConfig.DRIVER); /** * 创建数据的连接池中的连接对象 */ for(int i=0;i<DBConfig.MAX_POOL_SIZE;i++){ try { Connection connection = getConnection(); connection.setAutoCommit(false); DBPool.getInstance().addConnection(connection); } catch (SQLException e) { e.printStackTrace(); } } } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 用于获取一个数据库的Connection连接 * @return */ public static Connection getConnection(){ Connection connection = null; try { connection = DriverManager.getConnection(DBConfig.URL, DBConfig.USERNAME, DBConfig.PASSWORD); } catch (Exception e) { e.printStackTrace(); } return connection; } }
package com.myframework.db; import java.sql.Connection; /** * 连接池的接口 * @author xiajie * */ public interface IDBPool { /** * 获取数据库连接 * Connection 是jdk底层对数据连接的封装接口 * @return */ public Connection getConnection(); /** * 释放数据库链接 */ public void relaseConnection(Connection connection); /** * 添加对数据的一次连接线程 * @param connection */ public void addConnection(Connection connection); }
package com.myframework.db; import java.sql.Connection; import java.sql.SQLException; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.LinkedBlockingQueue; public class DBPool implements IDBPool { private static volatile boolean isInit = false; private static DBPool dbPool = new DBPool(); private volatile int n=0; //私有化构造方法是为了让在 new 对象时不能采用new DBPool()的方式 private DBPool(){} /** * 使用线程安全的单例模式 * <p>Title: getInstance</p> * <p>Description: </p> * @return */ public synchronized static DBPool getInstance(){ if(isInit == false){ isInit = true; dbPool.initPool(); } return dbPool; } public void initPool(){ DBManager.initDBPool(); } /** * 用来存放对数据库一次连接Connection的java并发包中的对象 */ //private static ConcurrentLinkedQueue<Connection> pools = new ConcurrentLinkedQueue<Connection>(); private static BlockingQueue<Connection> pools = new LinkedBlockingQueue<Connection>(); @Override public Connection getConnection() { /** * 从初始时加入了20个connection的队列中获取取出队头的元素 * 这样可以保证元素的个数不变 */ Connection conn = null; try { conn = pools.take(); } catch (InterruptedException e) { e.printStackTrace(); } //防止在使用过程中变为null if(conn == null){ conn = DBManager.getConnection(); } return conn; } @Override public void relaseConnection(Connection connection) { try { if(connection.isClosed() == false){ pools.add(connection); }else{ /** * 如果连接已经关闭了, * 为了保证连接池中的线程数量不变,应该在创建一个线程添加到连接线程队列 */ Connection conection = DBManager.getConnection(); pools.add(conection); } } catch (SQLException e) { e.printStackTrace(); } } @Override public void addConnection(Connection connection) { pools.add(connection); } }
package com.myframework.db; import com.mysql.jdbc.Connection; public class DBTest { public static void main(String[] args) { for(int i=1;i<=40;i++){ Connection connection = (Connection) DBPool.getInstance().getConnection(); System.out.println(connection+" "+i); DBPool.getInstance().relaseConnection(connection); } } }
com.mysql.jdbc.Connection@1a53929c 1 com.mysql.jdbc.Connection@64be4d44 2 com.mysql.jdbc.Connection@9c2df08 3 com.mysql.jdbc.Connection@58c08b39 4 com.mysql.jdbc.Connection@48f478b4 5 com.mysql.jdbc.Connection@2a2096d7 6 com.mysql.jdbc.Connection@418f12dc 7 com.mysql.jdbc.Connection@181f4b24 8 com.mysql.jdbc.Connection@2e7e34db 9 com.mysql.jdbc.Connection@5fc02db5 10 com.mysql.jdbc.Connection@41f8f72f 11 com.mysql.jdbc.Connection@402c507f 12 com.mysql.jdbc.Connection@1d58e2c3 13 com.mysql.jdbc.Connection@368f7f42 14 com.mysql.jdbc.Connection@6ebe20a 15 com.mysql.jdbc.Connection@68450212 16 com.mysql.jdbc.Connection@a8b2139 17 com.mysql.jdbc.Connection@34322a97 18 com.mysql.jdbc.Connection@498a3a46 19 <span style="color:#ff0000;">com.mysql.jdbc.Connection@11f7ef62 20</span> com.mysql.jdbc.Connection@1a53929c 21 com.mysql.jdbc.Connection@64be4d44 22 com.mysql.jdbc.Connection@9c2df08 23 com.mysql.jdbc.Connection@58c08b39 24 com.mysql.jdbc.Connection@48f478b4 25 com.mysql.jdbc.Connection@2a2096d7 26 com.mysql.jdbc.Connection@418f12dc 27 com.mysql.jdbc.Connection@181f4b24 28 com.mysql.jdbc.Connection@2e7e34db 29 com.mysql.jdbc.Connection@5fc02db5 30 com.mysql.jdbc.Connection@41f8f72f 31 com.mysql.jdbc.Connection@402c507f 32 com.mysql.jdbc.Connection@1d58e2c3 33 com.mysql.jdbc.Connection@368f7f42 34 com.mysql.jdbc.Connection@6ebe20a 35 com.mysql.jdbc.Connection@68450212 36 com.mysql.jdbc.Connection@a8b2139 37 com.mysql.jdbc.Connection@34322a97 38 com.mysql.jdbc.Connection@498a3a46 39 <span style="color:#ff0000;">com.mysql.jdbc.Connection@11f7ef62 40</span>
六.对连接池的优化思路
1.可以设计多个BolckingQueue
因为对这个队列的每次take(),put()操作,都把,连接池锁住了。比如说有100个线程去操作队列,但是同时只能有1个线程在put(),take()操作,这时是加锁的,其余的99个线程都要等待。有了多个BolckingQueue后就可以提高操作效率。
2.判断 每一个队列中还有多少,根据队列里存放的数量来动态的分配从哪个队列中取,加到哪个队列中。
3.通过计算hash值取模的方法,负载均衡到不同的队列中