📄 connectionmanager.java
字号:
package util.database;
import java.sql.*;
import java.util.*;
/**
* ConnectionManager
* 数据库连接的管理类,使用连接池。默认的最小连接数和最大连接数分别为5,10。
* 如果用户指定的值大于默认值,就采用指定的值
*
* @author Michael Zeng
* @version 1.0 September 18, 2002
*
* @todo: 目前还只能支持一个数据库和一个连接池。因为在构造函数中指定了数据库的
* 各种参数,不是很灵活。下一步采用loadProperty()方法从一个配置文件中直接读取参
* 数,并且考虑支持多个连接池。
*/
public class ConnectionManager
{
private static ConnectionManager instance = null;
private ConnectionPool connPool = null;
private String driver, url, user, passwd;
private int minConn = 5, maxConn = 10;
private final long PERIOD = 20000; //线程等待的时间20秒
private final int TRY_TIMES = 5; //池中没有可用连接时的重试次数
/**
* 得到ConnectionManager的一个唯一实例
*
* @param _driver 数据库驱动程序
* @param _url 数据库的地址
* @param _user 数据库用户名
* @param _passwd 用户密码
* @param _minConn 最小支持的连接数目
* @param _maxConn 最大支持的连接数目
* @return ConnectionManager 唯一实例
*
* @throws Exception
*/
public static ConnectionManager getInstance(String _driver, String _url, String _user,
String _passwd, int _minConn, int _maxConn) throws Exception
{
if(instance == null)
{
instance = new ConnectionManager(_driver, _url, _user, _passwd,
_minConn, _maxConn);
}
return instance;
}
/**
* 从连接池中得到Conncetion的一个实例
*
* @return Connection 连接的实例,出现异常情况时,返回null
*
* @throws Exception
*/
public Connection getConnection() throws Exception
{
return this.connPool.getConnection();
}
/**
* 把一个Connection实例返回连接池,如果已经到了池的最大容量,
* 就把这个连接释放。
*
* @param conn 要返回的Connection
*
* @throws Exception
*/
public void freeConncetion(Connection conn) throws Exception
{
this.connPool.freeConncetion(conn);
}
/**
* 释放连接池中的所有Connection
*
* @throws Exception
*/
public void close()throws Exception
{
this.connPool.release();
}
/**
* 得到连接池的实际大小
*
* @return int 连接池的大小
*/
public int getPoolSize()
{
return this.connPool.getPoolSize();
}
/**
* 私有的构造函数
*
* @param _driver 数据库驱动程序
* @param _url 数据库的地址
* @param _user 数据库用户名
* @param _passwd 用户密码
* @param _minConn 最小支持的连接数目
* @param _maxConn 最大支持的连接数目
* @return ConnectionManager 实例
*
* @throws Exception
*/
private ConnectionManager(String _driver, String _url, String _user,
String _passwd, int _minConn, int _maxConn) throws Exception
{
this.driver = _driver;
this.url = _url;
this.user = _user;
this.passwd = _passwd;
//如果用户指定的值大于默认值,就采用指定的值
this.minConn = Math.max(this.minConn, _minConn);
this.maxConn = Math.max(this.maxConn, _maxConn);
//如果用户指定的min > max,强迫两个值相等
this.minConn = Math.min(this.minConn, this.maxConn);
this.connPool = new ConnectionPool();
}
/**
* ConnectionPool
* inner class
*/
private class ConnectionPool implements Runnable
{
private List pool = null;
private Thread runner = null;
private boolean runOver = false;//是否结束线程的标识
/**
* 构造函数,初始化连接池中的Connection
*
* @throws Exception
*/
public ConnectionPool() throws Exception
{
this.pool = new LinkedList();
//初始化最小数量的Connection
for (int i = 0; i < minConn; i++)
{
this.pool.add(this.createConnection());
}
//启动线程
runner = new Thread(this);
runner.start();
}
/**
* 实现Runnable接口的方法。在后台进行周期性的检测,保证连接池中的可用
* 连接数目不小于最小连接数目
*/
public void run()
{
while (true)
{
if(runOver == true) return;
//当可用连接数目小于最小连接数目,表达式(minConn - pool.size())
//的结果是大于0的整数,执行循环
int numOfLack = 0;
if(this.pool != null) numOfLack = minConn - pool.size();
for (int i = 0; i < numOfLack; i++)
{
try{ this.pool.add(this.createConnection()); }
catch (Exception ex){}
}
try{ Thread.sleep(PERIOD); }
catch (InterruptedException ex){}
}// end of while()
}
/**
* 从连接池中得到Conncetion的一个实例
*
* @return Connection 连接的实例,出现异常情况时,返回null
*
* @throws Exception
*/
public synchronized Connection getConnection() throws Exception
{
Connection conn = null;
//进行指定次数的尝试
for (int i = 0; i < TRY_TIMES; i++)
{
if(this.pool.size() > 0)
{
//取得池中的第一个
conn = (Connection)this.pool.remove(0);
break;
}
else
{
//等待半个周期
wait(PERIOD / 2);
}
}
//如果经过等待仍然没有可用的连接(某种异常情况),返回null
if(conn == null) return null;
//如果取得的连接不可用,递归调用自己
if(conn.isClosed()) conn = this.getConnection();
return conn;
}
/**
* 把一个Connection实例返回连接池,如果已经到了池的最大容量,
* 就把这个连接释放。
*
* @param conn 要返回的Connection
*
* @throws Exception
*/
public synchronized void freeConncetion(Connection conn) throws Exception
{
//无效的连接不需要返回池中
if(conn == null || conn.isClosed()) return;
if(this.pool.size() < maxConn )
this.pool.add(conn);
else
conn.close();
}
/**
* 释放连接池中的所有Connection
*
* @throws Exception
*/
public synchronized void release()throws Exception
{
Connection conn = null;
for (int i = 0; i < this.pool.size(); i++)
{
conn = (Connection)this.pool.get(i);
conn.close();
}
conn = null;
this.pool = null;
this.runOver = true; //是否结束线程的标识
}
/**
* 得到连接池的实际大小
*
* @return int 连接池的大小
*/
public int getPoolSize()
{
return this.pool.size();
}
/**
* helper方法,建立一个数据库的连接
*
* @return Connection 数据库的连接
* @throws Exception
*/
private Connection createConnection() throws Exception
{
Class.forName(driver);
return DriverManager.getConnection(url,user, passwd);
}
}// inner class ConnectionPool
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -