手写数据库链接池

实现手写数据库链接池

引入Pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.cy</groupId>
    <artifactId>my-jdbc-pool</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
        </dependency>
    </dependencies>

</project>

定义链接池接口

public interface IConnectionPool {

    public Connection getConnection();

    public void releaseConnection(Connection connection);

}

手动封装工具类

//外部配置文件信息
public class DbBean {

	/* 链接属性 */
	private String driverName = "com.mysql.jdbc.Driver";

	private String url = "jdbc:mysql://localhost:3306/test";

	private String userName = "root";

	private String password = "chengyang";

	private String poolName = "thread01";// 连接池名字

	private int minConnections = 1; // 空闲池,最小连接数

	private int maxConnections = 10; // 空闲池,最大连接数

	private int initConnections = 5;// 初始化连接数

	private long connTimeOut = 1000;// 重复获得连接的频率

	private int maxActiveConnections = 100;// 最大允许的连接数,和数据库对应

	private long connectionTimeOut = 1000 * 60 * 20;// 连接超时时间,默认20分钟

	public String getDriverName() {
		return driverName;
	}

	public void setDriverName(String driverName) {
		this.driverName = driverName;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getPoolName() {
		return poolName;
	}

	public void setPoolName(String poolName) {
		this.poolName = poolName;
	}

	public int getMinConnections() {
		return minConnections;
	}

	public void setMinConnections(int minConnections) {
		this.minConnections = minConnections;
	}

	public int getMaxConnections() {
		return maxConnections;
	}

	public void setMaxConnections(int maxConnections) {
		this.maxConnections = maxConnections;
	}

	public int getInitConnections() {
		return initConnections;
	}

	public void setInitConnections(int initConnections) {
		this.initConnections = initConnections;
	}

	public long getConnTimeOut() {
		return connTimeOut;
	}

	public void setConnTimeOut(long connTimeOut) {
		this.connTimeOut = connTimeOut;
	}

	public int getMaxActiveConnections() {
		return maxActiveConnections;
	}

	public void setMaxActiveConnections(int maxActiveConnections) {
		this.maxActiveConnections = maxActiveConnections;
	}

	public long getConnectionTimeOut() {
		return connectionTimeOut;
	}

	public void setConnectionTimeOut(long connectionTimeOut) {
		this.connectionTimeOut = connectionTimeOut;
	}

}

编写链接池的逻辑代码

/**
 * 数据库连接池实现原理 
* ####核心参数######
* 1.空闲线程 容器 没有被使用的连接存放 2.活动线程 容器正在使用的连接
* ###核心步骤#####
* 2.1 初始化线程池(初始化空闲线程)
* 3.1 调用getConnection方法 --- 获取连接
* ####3.1.1 先去freeConnection获取当前连接,存放在activeConnection
* 4.1 调用releaseConnection方法 ----释放连接----资源回收
* ####4.1.1 获取activeConnection集合连接,转移到 freeConnection集合中
*/
public class ConnectionPool implements IConnectionPool { // 使用线程安全的集合 空闲线程 容器 没有被使用的连接存放 private List<Connection> freeConnection = new Vector<Connection>(); // 使用线程安全的集合 活动线程 容器 容器正在使用的连接 private List<Connection> activeConnection = new Vector<Connection>(); private DbBean dbBean; private int countConne = 0; public ConnectionPool(DbBean dbBean) { // 获取配置文件信息 this.dbBean = dbBean; init(); } // 初始化线程池(初始化空闲线程) private void init() { if (dbBean == null) { return;// 注意最好抛出异常 } // 1.获取初始化连接数 for (int i = 0; i < dbBean.getInitConnections(); i++) { // 2.创建Connection连接 Connection newConnection = newConnection(); if (newConnection != null) { // 3.存放在freeConnection集合 freeConnection.add(newConnection); } } } // 创建Connection连接 private synchronized Connection newConnection() { try { Class.forName(dbBean.getDriverName()); Connection connection = DriverManager.getConnection(dbBean.getUrl(), dbBean.getUserName(), dbBean.getPassword()); countConne++; return connection; } catch (Exception e) { return null; } } // 调用getConnection方法 --- 获取连接 public synchronized Connection getConnection() { try { Connection connection = null; // 当前创建的连接>最大连接数 if (countConne < dbBean.getMaxActiveConnections()) { // 小于最大活动连接数 // 1.判断空闲线程是否有数据 if (freeConnection.size() > 0) { // 空闲线程有存在连接 // ==freeConnection.get(0);freeConnection.remove(0) // 拿到在删除 connection = freeConnection.remove(0); } else { // 创建新的连接 connection = newConnection(); } // 判断连接是否可用 boolean available = isAvailable(connection); if (available) { // 存放在活动线程池 activeConnection.add(connection); countConne++; } else { countConne--; connection = getConnection();// 怎么使用重试? 递归算法 } } else { // 大于最大活动连接数,进行等待 wait(dbBean.getConnTimeOut()); // 重试 connection = getConnection(); } return connection; } catch (Exception e) { return null; } } // 判断连接是否可用 public boolean isAvailable(Connection connection) { try { if (connection == null || connection.isClosed()) { return false; } } catch (Exception e) { // TODO: handle exception } return true; } // 释放连接 回收 public synchronized void releaseConnection(Connection connection) { try { // 1.判断连接是否可用 if (isAvailable(connection)) { // 2.判断空闲线程是否已满 if (freeConnection.size() < dbBean.getMaxConnections()) { // 空闲线程没有满 freeConnection.add(connection);// 回收连接 } else { // 空闲线程已经满 connection.close(); } activeConnection.remove(connection); countConne--; notifyAll(); } } catch (Exception e) { // TODO: handle exception } } }
注意:等待机制和重试机制!

手动实现调用链接池的工具类

// 管理线程池
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 Test001 {

	public static void main(String[] args) {
		ThreadConnection threadConnection = new ThreadConnection();
		for (int i = 1; i < 3; i++) {
			Thread thread = new Thread(threadConnection, "线程i:" + i);
			thread.start();
		}
	}
}

class ThreadConnection implements Runnable {

	public void run() {
		for (int i = 0; i < 10; i++) {
			Connection connection = ConnectionPoolManager.getConnection();
			System.out.println(Thread.currentThread().getName() + ",connection:" + connection);
			ConnectionPoolManager.releaseConnection(connection);
		}
	}
}

结果

线程i:2,connection:com.mysql.cj.jdbc.ConnectionImpl@449d6465
线程i:1,connection:com.mysql.cj.jdbc.ConnectionImpl@131c736d
线程i:1,connection:com.mysql.cj.jdbc.ConnectionImpl@1ddb9f7e
线程i:1,connection:com.mysql.cj.jdbc.ConnectionImpl@19e4181d  复用
线程i:2,connection:com.mysql.cj.jdbc.ConnectionImpl@73331eae
线程i:1,connection:com.mysql.cj.jdbc.ConnectionImpl@131c736d
线程i:1,connection:com.mysql.cj.jdbc.ConnectionImpl@1ddb9f7e
线程i:1,connection:com.mysql.cj.jdbc.ConnectionImpl@19e4181d  复用
线程i:1,connection:com.mysql.cj.jdbc.ConnectionImpl@73331eae
线程i:1,connection:com.mysql.cj.jdbc.ConnectionImpl@131c736d
线程i:1,connection:com.mysql.cj.jdbc.ConnectionImpl@1ddb9f7e
线程i:1,connection:com.mysql.cj.jdbc.ConnectionImpl@19e4181d  复用
线程i:2,connection:com.mysql.cj.jdbc.ConnectionImpl@449d6465
线程i:2,connection:com.mysql.cj.jdbc.ConnectionImpl@73331eae
线程i:2,connection:com.mysql.cj.jdbc.ConnectionImpl@131c736d
线程i:2,connection:com.mysql.cj.jdbc.ConnectionImpl@1ddb9f7e
线程i:2,connection:com.mysql.cj.jdbc.ConnectionImpl@19e4181d  复用
线程i:2,connection:com.mysql.cj.jdbc.ConnectionImpl@449d6465
线程i:2,connection:com.mysql.cj.jdbc.ConnectionImpl@73331eae
线程i:2,connection:com.mysql.cj.jdbc.ConnectionImpl@131c736d

你可能感兴趣的:(链接池,jdbc,线程)