简单数据库连接池-总结
一、代码实现
//参数配置类 public class DbBean { private String driverName="com.mysql.jdbc.Driver"; //数据库驱动名称 private String url="jdbc:mysql://localhost:3306/iodn";//数据库连接地址 private String username="root";//用户名 private String userpwd="odn2018";//密码 private String poolName="thread01";//池名 private int minConnection=1;//最小连接数 private int maxConnection=5;//最大连接数 private int initConnection=3;//初始化连接数 private long connectOut=100000;//重试连接的时间 private int maxActiveConnection=100;//最大可连接的数量 private long connectOverOut=60*1000;//连接超时时间 } //连接池业务逻辑类 public class ConnectionPool { private List<Connection> freeConnection=new Vector<>(); private List<Connection> activeConnection=new Vector<>(); private DbBean dbBean; private int connectionCount=0; public ConnectionPool(DbBean dbBean){ this.dbBean=dbBean; init(); } //连接池初始化方法 private void init() { if(dbBean==null){ throw new RuntimeException("数据库初始化参数不能为空"); } for(int i=0;i<dbBean.getInitConnection();i++){ Connection newConnection=newConnection(); if(newConnection!=null){ System.out.println("初始化添加到空闲池"); freeConnection.add(newConnection); System.out.println("空闲池大小"+freeConnection.size()); } } } //数据库创建连接 public Connection newConnection() { System.out.println("新建一个连接"); try { Class<?> connectionClass= Class.forName(dbBean.getDriverName()); Connection connection= DriverManager.getConnection(dbBean.getUrl(),dbBean.getUsername(),dbBean.getUserpwd()); return connection; } catch (Exception e) { e.printStackTrace(); return null; } } //数据库获取连接 public synchronized Connection getConnection(){ Connection connection = null; if(connectionCount<dbBean.getMaxConnection()){//小于最大的连接数 if(freeConnection.size()>0){ connection=freeConnection.remove(0); }else{ connection=newConnection(); } if(isAvailable(connection)){ activeConnection.add(connection); connectionCount++; }else{ getConnection(); } }else { try { System.out.println("等待重新获取,已经连接数="+connectionCount); wait(dbBean.getConnectOut()); connection=getConnection(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+"开始获取连接,连接总数:"+connectionCount); System.out.println(Thread.currentThread().getName()+"开始获取空闲连接数:"+freeConnection.size()); System.out.println(Thread.currentThread().getName()+"开始获取正在使用连接数:"+activeConnection.size()); return connection ; } private boolean isAvailable(Connection connection) { try { if(connection==null ||connection.isClosed()){ return false; } } catch (SQLException e) { e.printStackTrace(); return false; } return true; } public synchronized void releaseConnection(Connection connection){ if(isAvailable(connection)){ try { if(freeConnection.size()<dbBean.getInitConnection()){ freeConnection.add(connection); }else{ System.out.println("空闲数超过默认初始化值"); connection.close(); } connectionCount--; activeConnection.remove(connection); System.out.println(Thread.currentThread().getName()+"开始释放正在使用连接数:"+activeConnection.size()); System.out.println(Thread.currentThread().getName()+"开始释放空闲连接数:"+freeConnection.size()); System.out.println(Thread.currentThread().getName()+"开始释放连接,连接总数:"+connectionCount); notifyAll(); } catch (SQLException e) { e.printStackTrace(); } } } } //连接池入口管理类 public class ConnectionPoolManager { private static DbBean dbBean=new DbBean(); private static ConnectionPool connectionPool=new ConnectionPool(dbBean); public static Connection getConnection(){ return connectionPool.getConnection(); } public static void releaseConnection(Connection connection){ connectionPool.releaseConnection(connection); } } //多线程测试类 public class ThreadConnect implements Runnable { @Override public void run() { for (int i = 0; i <8; i++) { Connection connection=ConnectionPoolManager.getConnection(); System.out.println(Thread.currentThread().getName()+",connection:"+connection); ConnectionPoolManager.releaseConnection(connection); } } } //测试类 public class Test { public static void main(String[] args) throws InterruptedException { Long startTime=System.currentTimeMillis(); for(int i=0;i<40;i++){ Thread thread=new Thread(new ThreadConnect()); thread.start(); } Thread.sleep(3000); Long endTime=System.currentTimeMillis(); System.out.println("共耗时"+(endTime-startTime)); } }
二、总结
1、数据库连接池主要包含 参数配置类、连接池类、管理类以及测试类,连接池主要负责默认连接的初始化(池中默认已经创建的连接),连接的获取和连接的释放,连接主要的实现逻辑为,如果空闲连接池中有,则直接从池中获取连接,如果空闲池中没有,则创建新的连接(不超过最大连接,超过则等待其他线程释放)
2、连接池获取和释放线程用到了wait notify notifyAll 方法,用来控制线程因长时间等待而轮询获取连接,notityall 放在释放类中,当一个线程释放连接后,则换新其他线程获取连接(省去了等待的时间)