数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量﹑使用情况,为系统开发﹑测试及性能调整提供依据。
参考他人的一些方法,自己做了一个连接池,感觉里边还存在一些问题,希望大家能指正。
把Connection进行了包装,为ConnectionObject,里边包含Connection对象及其引用次数和建立时间等属性。
import java.sql.Connection;
public class ConnectionObject {
private Connection connection; //Connection对象
private int referTimes; //该对象已引用次数
private long bornDate; //该对象产生时间
public Connection getConnection() {
return connection;
}
public void setConnection(Connection connection) {
this.connection = connection;
}
public int getReferTimes() {
return referTimes;
}
public void setReferTimes(int referTimes) {
this.referTimes = referTimes;
}
public long getBornDate() {
return bornDate;
}
public void setBornDate(long bornDate) {
this.bornDate = bornDate;
}
}
ConnectionManager类,规定一些参数:
import java.io.IOException;
import java.io.InputStream;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;
public class ConnectionManager {
private static Timer timer = new Timer();
/**
* 单例模式(Singleton模式),构造方法为私有的。
*/
private ConnectionManager() {
loadDriver(mDriverName);
createPool();
}
/**
* 装载和注册所有JDBC驱动程序。
*/
private void loadDriver(String driverName) {
if (driverName != null && !"".equals(driverName)) {
try {
mDriver = (Driver) Class.forName(driverName).newInstance();
DriverManager.registerDriver(mDriver);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 创建连接池
*/
private void createPool() {
InputStream in = Conndb.class.getClassLoader().getResourceAsStream(
"/configure.properties");
Properties p = new Properties();
try {
p.load(in);
mDatabaseURL = p.getProperty("db.url");
mDatabaseUserName = p.getProperty("db.user");
mDatabasePassword = p.getProperty("db.password");
Class.forName("com.mysql.jdbc.Driver");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mDBConnectionPool = new ConnectionPool(mDatabasePassword, mDatabaseURL,
mDatabaseUserName, mNormalConnectNum, mMaxConnectNum);
if (mDBConnectionPool != null) {
System.out.println("创建连接池成功!");
} else {
System.out.println("创建连接池失败!");
}
}
/**
* 获取单例实例。
*/
public static synchronized ConnectionManager getInstance() {
if (mInstance == null) {
mInstance = new ConnectionManager();
//这里在创建完初始连接池后,即开始监测连接池的线程,每隔30分钟检测一次
timer.schedule(new TimerTask() {
@Override
public void run() {
mDBConnectionPool.checkPool();
}
}, timeDelay, timePeroid);
}
return mInstance;
}
public ConnectionObject getConnectionObject() {
if (mDBConnectionPool != null) {
return mDBConnectionPool.getConnection();
} else {
return null;
}
}
public ConnectionObject getConnection(long timeOut) {
if (mDBConnectionPool != null) {
return mDBConnectionPool.getConnection(timeOut);
}
return null;
}
public void releaseFreeConnection(ConnectionObject connectionObj) {
if (mDBConnectionPool != null) {
mDBConnectionPool.releaseFreeConnection(connectionObj);
}
}
/**
* 返回当前空闲连接数
*/
public int getnum() {
return mDBConnectionPool.getFreeConnectionNum();
}
/**
* 返回当前连接数
*/
public int getnumActive() {
return mDBConnectionPool.getCurrentConnectionNum();
}
/**
* 关闭所有连接,撤销驱动注册。
*/
public synchronized void release() {
/**
* 关闭连接
*/
mDBConnectionPool.release();
/**
* 撤销驱动
*/
try {
DriverManager.deregisterDriver(mDriver);
System.out.println("撤销JDBC驱动程序 " + mDriver.getClass().getName());
} catch (SQLException e) {
System.out.println("无法撤销JDBC驱动程序的注册:"
+ mDriver.getClass().getName());
}
}
private static ConnectionManager mInstance = null; // 定义唯一实例
private int mMaxConnectNum = 100;// 最大连接数
private int mNormalConnectNum = 10;// 保持连接数
private final static long timeDelay = 30 * 60 * 1000;// 第一次检测的时间延迟
private final static long timePeroid = 30 * 60 * 1000;// 每隔时间检测一次
private String mDatabasePassword = "";// 密码
private String mDatabaseURL = "jdbc:mysql://localhost/shop";// 连接URL
private String mDatabaseUserName = "root";// 用户名
private String mDriverName = "com.mysql.jdbc.Driver";// 驱动类
private Driver mDriver = null;// 驱动变量
private static ConnectionPool mDBConnectionPool = null;// 连接池实例变量
}
ConnectionPool类,主要功能都在这里:
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Vector;
public class ConnectionPool {
public ConnectionPool(String databasePassWord, String databaseURL,
String databaseUserName, int normalConnectionNum,
int maxConnectionNum) {
mDatabasePassWord = databasePassWord;
mDatabaseURL = databaseURL;
mDatabaseUserName = databaseUserName;
mMaxConnectionNum = maxConnectionNum;
/* 初始normalConnectionNum个连接 */
for (int i = 0; i < normalConnectionNum; i++) {
ConnectionObject connectionObj = createConnectionObject();
if (connectionObj != null) {
mFreeConnections.addElement(connectionObj);
mFreeConnectionNum++;
}
}
}
/* 创建一个新连接 */
private ConnectionObject createConnectionObject() {
ConnectionObject connectionObj = new ConnectionObject();
try {
if (mDatabaseUserName == null) {
connectionObj.setConnection(DriverManager
.getConnection(mDatabaseURL));
} else {
connectionObj.setConnection(DriverManager.getConnection(
mDatabaseURL, mDatabaseUserName, mDatabasePassWord));
}
} catch (SQLException e) {
e.printStackTrace();
}
connectionObj.setBornDate(System.currentTimeMillis());
connectionObj.setReferTimes(0);
return connectionObj;
}
/* 释放不用的连接到连接池 */
public synchronized void releaseFreeConnection(ConnectionObject conObj) {
mFreeConnections.addElement(conObj);
mFreeConnectionNum++;
mCheckedOut--;
mCurrentConnectionNum--;
notifyAll();
}
/* 返回当前空闲连接数 */
public int getFreeConnectionNum() {
return mFreeConnectionNum;
}
/* 返回当前连接数 */
public int getCurrentConnectionNum() {
return mCurrentConnectionNum;
}
// 获取一个可用连接
public synchronized ConnectionObject getConnection() {
ConnectionObject connectionObj = new ConnectionObject();
System.out.println("总连接数为:" + mMaxConnectionNum);
System.out.println("当前连接数为:" + mCurrentConnectionNum);
System.out.println("当前空闲连接数为:" + mFreeConnectionNum);
if (mFreeConnections.size() > 0) {
mFreeConnectionNum--;
connectionObj = (ConnectionObject) mFreeConnections.firstElement();
mFreeConnections.removeElementAt(0);
try {
if (connectionObj.getConnection().isClosed()) {
System.out.println("从连接池删除一个无效连接!");
connectionObj = getConnection();
}
} catch (SQLException e) {
System.out.println("从连接池删除一个无效连接!");
connectionObj = getConnection();
}
} else if (mMaxConnectionNum == 0 || mCheckedOut < mMaxConnectionNum) {
connectionObj = createConnectionObject();
}
if (connectionObj != null) { /* 当前连接数加1 */
connectionObj.setReferTimes(connectionObj.getReferTimes() + 1);
mCheckedOut++;
}
mCurrentConnectionNum++;
return connectionObj;
}
/* 获取一个连接, 并加上等待时间限制, 时间为毫秒 */
public synchronized ConnectionObject getConnection(long timeout) {
long startTime = new Date().getTime();
ConnectionObject connectionObj;
while ((connectionObj = getConnection()) == null) {
try {
wait(timeout);
} catch (InterruptedException e) {
}
if ((new Date().getTime() - startTime) >= timeout) {
return null; /* 超时返回 */
}
}
return connectionObj;
}
/* 关闭所有连接 */
public synchronized void release() {
Enumeration<ConnectionObject> connections = mFreeConnections.elements();
while (connections.hasMoreElements()) {
ConnectionObject connectionObj = (ConnectionObject) connections
.nextElement();
try {
connectionObj.getConnection().close();
mFreeConnectionNum--;
} catch (SQLException e) {
e.printStackTrace();
}
}
mFreeConnections.removeAllElements();
mCurrentConnectionNum = 0;
}
/* 定时检测连接池中connection,检测超时及引用次数超限,失效线程替换为新创建线程
* 这里我的解决方法感觉不太好
*/
public void checkPool() {
System.out.println("定时管理线程池");
long enterTime;
for (int i = 0; i < mFreeConnectionNum; i++) {
enterTime = System.currentTimeMillis();
if (enterTime - mFreeConnections.get(i).getBornDate() > 20 * 60 * 1000
|| mFreeConnections.get(i).getReferTimes() >= 10) {
ConnectionObject connectionObj = createConnectionObject();
mFreeConnections.get(i).setConnection(
connectionObj.getConnection());
mFreeConnections.get(i)
.setBornDate(connectionObj.getBornDate());
mFreeConnections.get(i).setReferTimes(
connectionObj.getReferTimes());
}
}
}
private Vector<ConnectionObject> mFreeConnections = new Vector<ConnectionObject>();
private int mCheckedOut;
private int mMaxConnectionNum;
private String mDatabasePassWord;
private String mDatabaseURL;
private String mDatabaseUserName;
private static int mFreeConnectionNum = 0;/* 空闲的连接数 */
private static int mCurrentConnectionNum = 0;/* 当前的连接数 */
}
自己手机app的后台目前用的是这个连接池,使用中暂时没有发现问题,一些问题需要之后完善。