你未必出类拔萃,但与众不同
手写简易数据连接池
创建一个maven项目
导入依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.11</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.11</version>
</dependency>
创建连接池信息
- 相当于在配置文件中抒写的连接池信息
@Data
@NoArgsConstructor
public class MyDbInfo {
/**
*驱动
*/
private String driverName = "com.mysql.cj.jdbc.Driver";
/**
* 数据库URL
*/
private String jdbcUrl = "jdbc:mysql://localhost:3306/bank?useSSL=false&serverTimezone=GMT";
/**
* 用户名
*/
private String userName = "root";
/**
* 密码
*/
private String password = "520560";
/**
* 连接池名
*/
private String poolName = "Thread01";
/**
* 小连接数
*/
private int minConnections = 1;
/**
* 小连接数
*/
private int maxConnections = 10;
/**
* 初始化连接数
*/
private int initConnections = 5;
/**
* 重复获得连接的频率
*/
private long connTimeOut = 1000;
/**
* 最大允许的连接数
*/
private int maxActiveConnections = 200;
/**
* 接超时时间,默认1分钟
*/
private long connectionTimeOut = 1000 * 60;
}
创建数据库连接池
创建一个接口 MyConnectionPoolInterface 给实现他的类定下规约
public interface MyConnectionPoolInterface {
/**
* 拿到连接
* @return
*/
Connection tryFetchConnection();
/**
* 释放连接
* @param connection
*/
void releaseConnection(Connection connection);
}
MyConnectionPool 连接池主要实现类
-
初始化线程池 根据配置的信息创建连接
-
获取新的连接
- 直接通过DriverManager进行获取
-
判断是否可用
- 判断当前连接是否关闭 或者为空
-
尝试获取连接tryFetchConnection
-
判断当前线程数是否小于最大线程数 是就继续判断是否有连接 有就直接返回 没有就创建
-
线程数要是大于最大线程池或者等于 就开始进行等待 等待释放连接后通知
-
再判断是否可用
-
public class MyConnectionPool implements MyConnectionPoolInterface{
/**
* 注入日志
*/
private Logger logger = LoggerFactory.getLogger(MyConnectionPool.class);
/**
* 线程池
*/
private LinkedList<Connection> pool = new LinkedList();
/**
* 注入bean
*/
private MyDbInfo myDbInfo;
/**
* 线程数
*/
private int countConnection = 0;
public MyConnectionPool(MyDbInfo myDbInfo) throws NullDbInfoException {
this.myDbInfo = myDbInfo;
init();
}
/**
* 初始话线程
*/
private void init() throws NullDbInfoException {
if (myDbInfo == null) {
throw new NullDbInfoException("myDbInfo == null");
}
// 获取初始化连接数
for (int i = 0; i < myDbInfo.getInitConnections(); i++) {
// 创建连接
Connection newConnection = getNewConnection();
pool.add(newConnection);
}
}
/**
* 获取新的连接
* @return
*/
private synchronized Connection getNewConnection() {
try {
Class.forName(myDbInfo.getDriverName());
} catch (ClassNotFoundException e) {
logger.error("Class.forName is error");
e.printStackTrace();
}
try {
Connection connection = DriverManager.getConnection(myDbInfo.getJdbcUrl(), myDbInfo.getUserName(),
myDbInfo.getPassword());
return connection;
} catch (SQLException e) {
logger.error("DriverManager.getConnection is error");
e.printStackTrace();
return null;
}
}
/**
* 尝试获取连接
* @return
*/
public synchronized Connection tryFetchConnection(){
Connection connection = null;
try {
if (countConnection < myDbInfo.getMaxActiveConnections()) {
// 判断线程池是否有连接
if (pool.size() > 0) {
return pool.removeFirst();
}else{
connection = getNewConnection();
}
// 判断连接是否可用
boolean available = isAvailable(connection);
if (available) {
// 存放在活动线程池
pool.add(connection);
countConnection++;
} else {
countConnection--;
connection = tryFetchConnection();
}
}else{
while(pool.isEmpty()){
pool.wait(myDbInfo.getConnTimeOut());
}
// 重试
connection = tryFetchConnection();
}
return connection;
} catch (InterruptedException e) {
e.printStackTrace();
logger.info("tryFetchConnection error");
}
return null;
}
/**
* 判断连接是否可用
* @param connection
* @return
*/
public boolean isAvailable(Connection connection) {
try {
if (connection == null || connection.isClosed()) {
return false;
}
} catch (Exception e) {
logger.error("connection is not available");
}
return true;
}
/**
* 释放连接
* @param connection
*/
public void releaseConnection(Connection connection){
synchronized (pool){
if(connection != null){
pool.add(connection);
//同时唤醒所有等待在pool的线程
pool.notifyAll();
}
}
}
}
创建连接池中心 进行调度
public class MyConnectionCenter {
private static MyDbInfo myDbInfo = new MyDbInfo();
private static MyConnectionPool myConnectionPool;
static {
try {
myConnectionPool = new MyConnectionPool(myDbInfo);
} catch (NullDbInfoException e) {
e.printStackTrace();
}
}
/**
* 获取连接 重复利用
* @return
*/
public static Connection getConnection() {
return myConnectionPool.tryFetchConnection();
}
/**
* 释放连接 回收
* @param connection
*/
public static void releaseConnection(Connection connection) {
myConnectionPool.releaseConnection(connection);
}
}
测试类
public class Demo {
public static void main(String[] args) {
ThreadConnection threadConnection = new ThreadConnection();
for (int i = 1; i < 3; i++) {
Thread thread = new Thread(threadConnection, "Thread:" + i);
thread.start();
}
}
}
class ThreadConnection implements Runnable {
public void run() {
for (int i = 0; i < 5; i++) {
Connection connection = MyConnectionCenter.getConnection();
System.out.println(Thread.currentThread().getName() + "getConnection:::" + connection);
MyConnectionCenter.releaseConnection(connection);
}
}
}