1. 程式人生 > >手寫 基礎 資料庫連線池

手寫 基礎 資料庫連線池

手寫資料庫連線池 基礎

 

 

package com.curiousby.baoyou.cn.showandshare.customised.dbpool.mysql;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Iterator;
import java.util.Vector;



public class MyCustomisedPool { 
	
	/**
	 * <pre>
	 * jdbcDriver = "com.mysql.jdbc.Driver"; // 資料庫驅動
	 * dbUrl = "jdbc:mysql://localhost:3306/database"; // 資料 URL
	 * dbUsername = "root"; // 資料庫使用者名稱
	 * dbPassword = "root"; // 資料庫使用者密碼
	 *  testSql = "select count(*) from t_user"; // 測試連線是否可用的測試表名,預設沒有測試表
	 *  initialConnections = 10; // 連線池的初始大小
	 *  incrementalConnections = 5;// 連線池自動增加的大小
	 *  maxConnections = 50; // 連線池最大的大小
	 *  </pre>
	 * @author baoy
	 */
	private DBConfig conf;
	private Vector<CustomisedConnection> connections;
	
	public static class CustomisedConnection{
		
		private  boolean busy = false;
		private Connection Connection = null;
		 
		public CustomisedConnection(Connection connection) {
			Connection = connection;
		}
		
		public boolean isBusy() {
			return busy;
		}
		public void setBusy(boolean busy) {
			this.busy = busy;
		}
		public Connection getConnection() {
			return Connection;
		}
		public void setConnection(Connection connection) {
			Connection = connection;
		} 
	}
	
	/**
	 * <pre>
	 * jdbcDriver = "com.mysql.jdbc.Driver"; // 資料庫驅動
	 * dbUrl = "jdbc:mysql://localhost:3306/database"; // 資料 URL
	 * dbUsername = "root"; // 資料庫使用者名稱
	 * dbPassword = "root"; // 資料庫使用者密碼
	 *  testSql = "select count(*) from t_user"; // 測試連線是否可用的測試表名,預設沒有測試表
	 *  initialConnections = 10; // 連線池的初始大小
	 *  incrementalConnections = 5;// 連線池自動增加的大小
	 *  maxConnections = 50; // 連線池最大的大小
	 *  </pre>
	 * @author baoy
	 */
	public static class DBConfig{
		private String jdbcDriver = "com.mysql.jdbc.Driver"; // 資料庫驅動
		private String dbUrl = "jdbc:mysql://localhost:3306/database"; // 資料 URL
		private String dbUsername = "root"; // 資料庫使用者名稱
		private String dbPassword = "root"; // 資料庫使用者密碼
		private String testSql = "select count(*) from t_user"; // 測試連線是否可用的測試表名,預設沒有測試表
		private int initialConnections = 10; // 連線池的初始大小
		private int incrementalConnections = 5;// 連線池自動增加的大小
		private int maxConnections = 50; // 連線池最大的大小
		
		public String getJdbcDriver() {
			return jdbcDriver;
		}
		public void setJdbcDriver(String jdbcDriver) {
			this.jdbcDriver = jdbcDriver;
		}
		public String getDbUrl() {
			return dbUrl;
		}
		public void setDbUrl(String dbUrl) {
			this.dbUrl = dbUrl;
		}
		public String getDbUsername() {
			return dbUsername;
		}
		public void setDbUsername(String dbUsername) {
			this.dbUsername = dbUsername;
		}
		public String getDbPassword() {
			return dbPassword;
		}
		public void setDbPassword(String dbPassword) {
			this.dbPassword = dbPassword;
		}
		public String getTestSql() {
			return testSql;
		}
		public void setTestSql(String testSql) {
			this.testSql = testSql;
		}
		public int getInitialConnections() {
			return initialConnections;
		}
		public void setInitialConnections(int initialConnections) {
			this.initialConnections = initialConnections;
		}
		public int getIncrementalConnections() {
			return incrementalConnections;
		}
		public void setIncrementalConnections(int incrementalConnections) {
			this.incrementalConnections = incrementalConnections;
		}
		public int getMaxConnections() {
			return maxConnections;
		}
		public void setMaxConnections(int maxConnections) {
			this.maxConnections = maxConnections;
		}
	}
	
	
	
	
	
	
	
	
	
	




	private Connection newConnection() throws SQLException{
		Connection conn = DriverManager.getConnection(conf.dbUrl, conf.dbUsername, conf.dbPassword);
		if (this.connections == null || this.connections.size() == 0) {
			int driverMaxConnections = conn.getMetaData().getMaxConnections();
			if (conf.maxConnections > 0 && driverMaxConnections <  conf.maxConnections ) {
				conf.maxConnections  = driverMaxConnections;
			}
		}
		return  conn;
	}
	
	private void createConnection(int nums) throws SQLException{
		for (int i = 0; i < nums; i++) {
			// 1如果 最大連線數大於0  
			// 1.1 並且 當前連線數小於最大連線數 ,可以
			// 1.2   當前連線數大於最大連線數,跳出(或者丟擲異常,超出最大連線數)
			// 2 如果 最大連線數小於0,無最大連線數限制 
			if (conf.maxConnections > 0 && this.connections.size()>= conf.maxConnections ) {
				break;
			}
			connections.add( new CustomisedConnection(newConnection()));
		}
	}
	 
	
	public synchronized  void  initConnection() throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException{
		if (connections != null) {
			return;
		}
		Driver driver = (Driver) (Class.forName(conf.jdbcDriver).newInstance());
		DriverManager.registerDriver(driver);
		connections = new Vector<CustomisedConnection>();
		createConnection(conf.initialConnections);
	}
	
	private CustomisedConnection findFreeConnection() throws SQLException {
		Iterator<CustomisedConnection> iterator = connections.iterator();
		while (iterator.hasNext()) { 
			CustomisedConnection customisedConnection = iterator.next();
			if (!customisedConnection.isBusy()) {
				Connection connection = customisedConnection.getConnection();
				if (!testConnection(connection)) {
					connection = newConnection();
					customisedConnection.setConnection(connection);
				}
				customisedConnection.setBusy(true);
				return customisedConnection;
			}
		}
		return null;
	}
	
	private boolean testConnection(Connection connection) throws SQLException {
		if (conf.getTestSql() != null && !"".equals(conf.getTestSql())) {
			try{
			Statement stmt = connection.createStatement();
			stmt.execute(conf.getTestSql());
			}catch(Exception e){
				e.printStackTrace();
				closeConnection(connection); 
				return false;
			}
		}
		return true;
	}

	private  CustomisedConnection getFreeCustomisedConnection() throws SQLException { 
		CustomisedConnection findFreeConnection = findFreeConnection();
		if (findFreeConnection != null) {
			return findFreeConnection;
		}
		if (conf.maxConnections > 0 &&   conf.maxConnections  > connections.size() ) {
			int nums =  conf.maxConnections  > connections.size()+conf.incrementalConnections ? conf.incrementalConnections : conf.maxConnections-  connections.size();
			createConnection(nums);
		}
		return findFreeConnection();
	}

	
	public synchronized CustomisedConnection getConnection() throws SQLException{
		if (connections == null) {
			return null;
		}
		CustomisedConnection conn = getFreeCustomisedConnection();
		while (conn == null) {
			try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); }
			conn = getFreeCustomisedConnection();
		}
		return conn;
	}
	
	public synchronized void returnConnection(Connection conn){
		Iterator<CustomisedConnection> iterator = connections.iterator();
		while (iterator.hasNext()) { 
			CustomisedConnection customisedConnection = iterator.next();
			if (conn == customisedConnection.getConnection()) { 
				customisedConnection.setBusy(false);
			}
		}
	}
	 
	public synchronized void  closeConnection(Connection conn) {
		Iterator<CustomisedConnection> iterator = connections.iterator();
		while (iterator.hasNext()) { 
			CustomisedConnection customisedConnection = iterator.next();
			if (conn == customisedConnection) {  
				//設定成true 沒有執行緒繼續訪問它
				customisedConnection.setBusy(true);
				//關閉連線
				Connection connection = customisedConnection.getConnection();
				try { connection.close(); } catch (SQLException e) {  e.printStackTrace(); }
				// 從池中移除
				connections.remove(customisedConnection);
			}
		} 
	}

	public int getPoolSize(){
		if (connections == null) {
			return 0;
		}
		return connections.size();
	} 
	 
	
	public DBConfig getConf() {
		return conf;
	}

	public void setConf(DBConfig conf) {
		this.conf = conf;
	}

	public Vector<CustomisedConnection> getConnections() {
		return connections;
	}

	public void setConnections(Vector<CustomisedConnection> connections) {
		this.connections = connections;
	}
	 
	public MyCustomisedPool(DBConfig conf) {
		this.conf = conf;
	}

	
	
	
	
	
	//test 
	public static void main(String[] args) throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException {
		MyCustomisedPool pool = new MyCustomisedPool(new DBConfig() );
		pool.initConnection(); 
		for (int i = 0; i < 1000; i++) {
			CustomisedConnection connection = pool.getConnection();
			System.out.println(pool.getPoolSize());
			try{
				pool.testConnection(connection.getConnection());
			}catch(Exception e){
				e.printStackTrace();
				pool.closeConnection(connection.getConnection());
			}finally{
				pool.returnConnection(connection.getConnection());
			}
		}
	}
	
}

 

 

 

 

 

 

 

 

 

 

 

 

捐助開發者 

在興趣的驅動下,寫一個免費的東西,有欣喜,也還有汗水,希望你喜歡我的作品,同時也能支援一下。 當然,有錢捧個錢場(支援支付寶和微信 以及扣扣群),沒錢捧個人場,謝謝各位。

 

個人主頁http://knight-black-bob.iteye.com/



 
 
 謝謝您的贊助,我會做的更好!