什么是数据库连接池?
数据库连接的建立是一种耗时、性能低、代价高的操作,频繁的数据库连接的建立和关闭极大的影响了系统的性能。数据库连接池是系统初始化过程中创建一定数量的数据库连接放于连接池中,当程序需要访问数据库时,不再建立一个新的连接,而是从连接池中取出一个已建立的空闲连接,使用完毕后,程序将连接归还到连接池中,供其他请求使用,从而实现的资源的共享,连接的建立、断开都由连接池自身来管理。
数据库连接池为系统的运行带来了以下优势:昂贵的数据库连接资源得到重用;减少了数据库连接建立和释放的时间开销,提高了系统响应速度;统一的数据库连接管理,避免了连接资源的泄露。
数据库连接池创建过程
1. 创建一个ConnectionPool,初始化一定的Connection连接,存放在Vector(线程安全)列表里。作为空闲对列。
2. 创建一个AtomicInteger类型的currentActive,作为记录活动连接。
3. 创建一个ConnectionPoolEntry对象,封装Connection和使用初始时间,为了防止长时间占用连接。
4. 创建一个ConnectionPoolEntry列表,作为工作线程。
5. 实现单例
6. 写一个获取连接方法。
7. 写一个回收连接方法。
8. 写一个监控方法,定时检查连接是否超时。
源码
DBPoolEntry类
package dbpool;
import java.sql.Connection;
public class DBPoolEntry {
private Connection connection;
private long userStartTime;
public DBPoolEntry(Connection connection, long userStartTime) {
super();
this.connection = connection;
this.userStartTime = userStartTime;
}
public Connection getConnection() {
return connection;
}
public long getUserStartTime() {
return userStartTime;
}
}
DBDataSource类
package dbpool;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
public class DBDataSource {
// 当前活跃的连接
private AtomicInteger currentActive = new AtomicInteger(0);
// 空闲连接池
private Vector<Connection> freePools = new Vector<Connection>();
private DBConfig config;
// 正在工作的线程
private Vector<DBPoolEntry> workPools = new Vector<>();
private final static DBDataSource dataSource = new DBDataSource();
// 实现单例
public static DBDataSource getDataSource() {
return dataSource;
}
private DBDataSource() {
super();
// TODO Auto-generated constructor stub
init();
checkConnection();
}
// 初始化连接池
private void init() {
// TODO Auto-generated method stub
config = new DBConfig();
try {
// 加载驱动
Class.forName(config.getDriver());
// 初始分配空闲连接
for (int i = 0; i < config.getInitSize(); i++) {
Connection connection = createConnection();
freePools.add(connection);
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 创建连接
private Connection createConnection() {
// TODO Auto-generated method stub
Connection connection = null;
try {
connection = DriverManager.getConnection(config.getUrl(), config.getUsername(), config.getPassword());
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
currentActive.incrementAndGet(); // 活跃连接加1
return connection;
}
// 获取连接
public synchronized Connection getConnection() {
Connection connection = null;
if (freePools.size() > 0) {
connection = freePools.get(0);
freePools.remove(0);
} else {
if (currentActive.get() < config.getMaxSize()) {
connection = createConnection();
} else {
try {
wait(1000);
return getConnection();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
}
}
}
// 得到工作连接初始工作时间,为了超时
long userStartTime = System.currentTimeMillis();
DBPoolEntry dbPoolEntry = new DBPoolEntry(connection, userStartTime);
workPools.add(dbPoolEntry);
return connection;
}
// 释放连接
public synchronized void releaseConnection(Connection connection) {
try {
if (!connection.isClosed()) {
freePools.add(connection);
for (DBPoolEntry dbPoolEntry : workPools) {
if (dbPoolEntry.getConnection() == connection) {
workPools.remove(dbPoolEntry);
break;
}
}
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 销毁连接
public void checkConnection() {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("活动数--->"+currentActive);
System.out.println("空闲对列数--->" + freePools.size());
System.out.println("工作队列数--->" + workPools.size());
System.out.println();
for (DBPoolEntry dbPoolEntry : workPools) {
long userStartTime = dbPoolEntry.getUserStartTime();
long currentTime = System.currentTimeMillis();
if (currentTime - userStartTime >= config.getTimeout()) {
try {
// 连接超时,关闭连接
dbPoolEntry.getConnection().close();
// 从工作对列里面删除
workPools.remove(dbPoolEntry);
// 活跃连接减1
currentActive.decrementAndGet();
break;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}, 50L, 1000L);
}
}
测试类
package dbpool;
import java.sql.Connection;
import java.util.Random;
public class DBConnectionPool {
/*
* 数据源
*/
private static DBDataSource dbDataSource = DBDataSource.getDataSource();
public static Connection getConnection() {
return dbDataSource.getConnection();
}
public static void close(Connection connection) {
dbDataSource.releaseConnection(connection);
}
public static void main(String[] args) {
MyThread myThread = new MyThread();
for (int j = 0; j < 1; j++) {
for (int i = 0; i < 60; i++) {
new Thread(myThread).start();
}
System.out.println("*----------*");
}
}
}
class MyThread implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
Connection connection = DBConnectionPool.getConnection();
try {
//模拟工作
Random random = new Random();
int i = random.nextInt(10);
Thread.sleep(i * 300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
DBConnectionPool.close(connection);
}
}
测试结果
*----------*
活动数--->9
空闲对列数--->0
工作队列数--->9
活动数--->10
空闲对列数--->5
工作队列数--->5
活动数--->10
空闲对列数--->3
工作队列数--->7
活动数--->10
空闲对列数--->5
工作队列数--->5
活动数--->10
空闲对列数--->7
工作队列数--->3
活动数--->10
空闲对列数--->5
工作队列数--->5
活动数--->10
空闲对列数--->4
工作队列数--->6
活动数--->10
空闲对列数--->4
工作队列数--->6
活动数--->10
空闲对列数--->4
工作队列数--->6
活动数--->9
空闲对列数--->3
工作队列数--->6
活动数--->8
空闲对列数--->6
工作队列数--->2
活动数--->7
空闲对列数--->7
工作队列数--->0
活动数--->7
空闲对列数--->7
工作队列数--->0