自定义实现了一个简单的连接池
已实现功能:
- 通过给定的初始大小,初始化固定数量的连接池。
- 通过maxsize指定最大连接池大小,当初始连接数不够用时,自动扩容,但不超过maxsize。
- 扩容之后若连接占用减少,连接池自动恢复到初始大小
(想到但)未实现功能:
- 线程不安全
- 获取连接失败无等待时间,直接给出异常。
- 如果线程池初始大小连接被长期占用,那么该线程池将毫无卵用。
package jdbc;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
public class MyDataSource {
private LinkedList<Connection> pool = new LinkedList<>(); // 存储连接的容器
private int initSize; // 初始连接池大小
private int maxSize; // 最大连接池大小
private int correctSize = 0; // 当前连接池大小,不是当前连接数量。
// 初始化
public MyDataSource(int initSize, int maxSize) {
this.initSize = initSize;
this.maxSize = maxSize;
for (int i = 0; i < initSize; i++) {
pool.add(this.createConnection());
correctSize++;
}
}
public Connection getConnection() {
// 如果连接池没有空,从连接池去连接
if (!pool.isEmpty()) {
return pool.remove();
} else if (correctSize < maxSize) { // 如果连接池空了但当先连接池大小小于最大值,那么新建连接并扩充连接池。
correctSize++;
return this.createConnection();
}
// 到这说明连接以达到最大,直接抛异常
throw new RuntimeException("连接池已满!");
}
private Connection createConnection() {
Connection connection = JDBCUtils.getConnection();
// 给出的是connection的代理对象,这里我们只增强了close方法。
return (Connection) Proxy.newProxyInstance(
connection.getClass().getClassLoader(),
new Class[]{Connection.class},
(proxy1, method, args) -> {
Object result = null;
// 当调用close方法的时候
if (method.getName().equals("close")) {
// 如果连接池内连接数量小于初始数量,就归还连接
if (pool.size() < initSize) {
pool.add((Connection) proxy1);
System.err.println("池内连接数量:" + pool.size() +
" 当前池大小:" + correctSize +
" 归还连接。。。");
} else { // 否则说明该连接为临时扩充所得,直接关闭连接并修改当前连接池大小。
method.invoke(connection, args);
correctSize--;
System.err.println("池内连接数量:" + pool.size() +
" 当前池大小:" + correctSize +
" 关闭连接。。。");
}
} else
result = method.invoke(connection, args);
return result;
}
);
}
public static void main(String[] args) throws SQLException {
MyDataSource myDataSource = new MyDataSource(3, 5);
Connection connection = myDataSource.getConnection();
Connection connection1 = myDataSource.getConnection();
connection1.close();
Connection connection2 = myDataSource.getConnection();
Connection connection3 = myDataSource.getConnection();
connection3.close();
Connection connection4 = myDataSource.getConnection();
Connection connection5 = myDataSource.getConnection();
Connection connection6 = myDataSource.getConnection();
connection6.close();
connection5.close();
connection4.close();
connection2.close();
}
}
附上JDBCUtils的代码
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ResourceBundle;
public class JDBCUtils {
// JDBC四打参数
private static String driverClass;
private static String url;
private static String username;
private static String password;
// 静态代码块,使加载驱动类只执行一次
static {
try {
// 加载配置文件获取数据
ResourceBundle bundle = ResourceBundle.getBundle("db");
driverClass = bundle.getString("driverClass");
url = bundle.getString("url");
username = bundle.getString("username");
password = bundle.getString("password");
// 加载驱动类
Class.forName(driverClass);
}catch (Exception e){
e.printStackTrace();
}
}
public static Connection getConnection(){
Connection conn = null;
try {
conn = DriverManager.getConnection(url,username,password);
}catch (Exception e){
e.printStackTrace();
}
return conn;
}
}
输出结果
从结果可以看出,当池大小不够时可以自动扩容到最大池大小。
调用关闭连接时,如果当前池大小是扩容的,还可以收缩回初始大小。