1. 程式人生 > 實用技巧 >簡單資料庫連線池-總結

簡單資料庫連線池-總結

一、程式碼實現

//引數配置類
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 放在釋放類中,當一個執行緒釋放連線後,則換新其他執行緒獲取連線(省去了等待的時間)