欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据库连接池

程序员文章站 2024-03-18 11:30:10
...


  

1 连接池的基本原理

  在对象池内部中,维护一定数量的数据库连接,并对外暴露数据库连接的获取和返回方法。如外部使用者可通过getConnection方法获取数据库连接,使用完毕后再通过releaseConnection方法将连接返回,注意此时的连接并没有关闭,而是由连接池管理器回收,并为下一次使用做好准备。

2 连接池的作用

  (1)资源的重用
  由于数据库连接得到了重用,避免了频繁创建、释放连接引起的大量性能开销,在减少系统消耗的基础上,增进了系统的平稳性(减少了内存碎片以及数据库的临时进程、线程的数量)
  (2)更快的系统响应速度
  直接利用现有的可用连接,避免了数据库的初始化和释放过程的时间开销,从而缩减了系统的响应时间
  (3)新的资源分配手段
  对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接的配置,实现数据库连接技术。
  (4)统一的连接管理,避免数据库连接泄露
  在较为完备的数据库连接池实现中,可根据预先的连接占用超时设定,强制收回被占用的连接,从避免了常规数据库连接操作中可能出现的连接泄露

3 配置信息

//外部配置文件信息
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 = "a123456";

	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分钟
	//省略setter/geter方法
}

4 数据库连接类

//连接数据库池
public interface IConnectionPool {

	// 获取连接(重复利用机制)
	public Connection getConnection();

	// 释放连接(可回收机制)
	public void releaseConnection(Connection connection);
}
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
		}

	}

}

5 线程池管理类

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);
	}
}

6 测试类

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);
		}
	}

}
相关标签: 手写