通常商业数据库JDBC驱动都会提供自已的数据库连接池管理器,无需自己制做。
无论如何,这里给出一个简单实现
实现连接池的关键点:
1. 单实例
2. 由实现类来管理数据库连接,包括连接,刷新
3. 重载java.sql.Connection的close功能。当客户程序调用close时不是真正的断开连接,而是将连接归还连接池管理器。
4. 将数据库属性独立于管理器本身
可选:
1. 实现javax.sql.PooledConnection
2. 实现javax.sql.DataSource
3. 实现javax.sql.ConnectionPoolDataSource
一个简单实现:
import java.io.*;
import java.util.*;
import java.sql.*;
public class ConnectionPool implements Runnable {
static String configFileName; // 如./connection-pool.properties
static Properties config;
private static List list = null;
private static boolean isCreate = false;
/**
* 实现单实例,关键点1
* @throws SQLException
*/
public ConnectionPool () throws SQLException {
if (list == null) init ();
if (!isCreate) {
Thread thread = new Thread(this);
thread.run();
isCreate = true;
}
}
public synchronized Connection getConnection () {
if (list == null) return null;
// 寻找空闲的连接
for (int i = 0; i < list.size(); i ++){
ConnectionWrap conn = (ConnectionWrap)list.get(i);
if (conn.free) {
conn.free = false;
conn.start = System.currentTimeMillis();
return conn;
}
}
// 没有空闲的连接则自动扩展
int step = Integer.parseInt(config.getProperty("step")); // 取得自动扩展的步长
this.addConnection(step);
return (ConnectionWrap)list.get(list.size() - step - 1);
}
public void run () {
long interval = Long.parseLong(config.getProperty("interval")); // 扫描时间
while (true) {
try {
Thread.sleep(interval);
} catch (Exception e) {
// 出错处理
}
scan ();
}
}
/**
* 关键点2,管理连接。一些超时的连接刷新
*/
private void scan () {
int timeout = Integer.parseInt(config.getProperty("timeout"));
for (int i = 0; i < list.size(); i ++) {
ConnectionWrap conn = (ConnectionWrap) list.get(i);
if (conn.start >; 0) {
time = System.currentTimeMillis() - conn.start;
if (time >;= timeout)
conn.close();
}
}
int initCount = Integer.parseInt(config.getProperty("init-count"));
if (list.size() >; initCount) { // 恢复到初始连接数
for (int i = list.size() - 1; i >; initCount; i --) {
ConnectionWrap conn = (ConnectionWrap) list.get(i);
if (conn.free) { // 真正地断开连接
try {
conn.conn.close();
} catch (SQLException ignore){}
list.remove(conn);
}
}
}
}
private void init () throws SQLException {
config = readConfig ();
createConnectionPool (config);
}
/**
* 读取配置文件
* @return java.util.Properties
* @throws SQLException
*/
private void readConfig () throws SQLException {
InputStream in = null;
try {
in = new FileInputStream (configFileName);
config = new Properties ();
config.load(in);
} catch (IOException ioe) { // 出错处理
throw new SQLException (ioe.getMessage());
} finally {
if (in != null)
try { in.close(); } catch (IOException ignore) {}
}
}
private void createConnectionPool () throws SQLException {
String driverName = config.getProperty("driver-name");
int initCount = Integer.parseInt(config.getProperty("init-count"));
int maxCount = Integer.parseInt(config.getProperty("max-count"));
try {
Driver driver = Class.forName(driverName);
addConnection (initCount);
} catch (Exception e) {
throw new SQLException (e.getMessage());
}
}
private void addConnection (int count) throws SQLException {
if (list == null) list = new ArrayList (count);
String url = config.getProperty("url");
String user = config.getProperty("user");
String password = config.getProperty("password");
for (int i = 0; i < count; i ++)
list.add(new ConnectionWrap (url, user, password));
}
class ConnectionWrap implements Connection {
Connection conn = null;
boolean free;
long start;
ConnectionWrap (String url, String user, String password) throws Exception {
Connection conn = DriverManager.getConnection(url, user, password);
free = true;
}
/**
* 这里关键点3,并不真正断开连接,而是归还给管理器
* @return
* @throws SQLException
*/
public boolean close () throws SQLException {
free = true;
start = 0;
}
// 其他java.sql.Connection的方法
// ...
}
}
配置文件示例
driver-name = oracle.jdbc.driver.Driver
url = jdbc:oracle:thin:@host:1521:employee
user = scott
password = tiger
timeout = 60000 # 一分钟
init-count = 10
step = 5
interval = 1000 # 1秒
...
以后在客户端可以这么调用
ConnectionPool pool = new ConnectionPool ();
Connection conn = null;
try {
conn = pool.getConnection ();
// 其他操作
} finally {
if (conn != null) conn.close ();
}
限于篇幅,javax.sql.DataSource, javax.sql.ConnectionPoolDataSource等就不一一列出了
posted on 2006-06-06 20:36
zjw_albert 阅读(259)
评论(0) 编辑 收藏