最近在IBM websphere portal的项目中,碰到大量的portlet需要连接数据库,而连接数据库的开销造成性能问题,因此考虑在portal中使用连接池。方案1)使用portal的连接池,可惜IBM的连接池使用起来很是不爽,问题多多,放弃。方案2)自己写连接池,其实质是connection对象池。在portal 项目中开发连接池,要解决的问题,是数据库驱动程序的位置。本方案借助于连接创建和连接池分开的方法实现。
本应用包含三个类,如下:
ConnectionPool 连接池管理类
AddConnectionProcess 连接维护线程类
DbSource 创建数据库连接接口类
public class ConnectionPool {
private Vector pool = new Vector();
private String name;//暂时没有使用
private int maxConn;//最大连接数
private int normalConn;//正常连结数
private int minConn;//最小连接数
private DbSource dbSource;
private boolean addThreadFlag = false;
private static ConnectionPool instance=null;
private void init(DbSource dbSource,String name, int maxConn, int normalConn, int minConn) throws Exception {
this.name = name;
this.maxConn=maxConn;
this.normalConn = normalConn;
this.minConn = minConn;
this.dbSource=dbSource;
addThreadFlag = true;
Thread thread = new Thread(new AddConnectionProcess(this));//初始化连接池
thread.start();
}
public static ConnectionPool getInstance(DbSource dbSource, int maxConn, int normalConn,int minConn)throws Exception {
if(instance==null){
synchronized(ConnectionPool.class){
if(instance==null){
instance = new ConnectionPool();
instance.init(dbSource,"DB2",maxConn,normalConn,minConn);
}
}
}
return instance;
}
public static ConnectionPool getInstance(){
return instance;
}
/**
* 将不再使用的连接返回给连接池
*
* @param conn 客户程序释放的连接
* @param repeat连接重复使用标志
*/
public synchronized void freeConnection(Connection conn, boolean repeat) {
// 将指定连接加入到向量末尾
if(conn==null)
return;
if (repeat && pool.size()<maxConn)
pool.add(conn);
else {
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
//notifyAll();
}
/**
* 考虑到线程的执行效率,在这里不考虑连接的有效性
* 注意:连接的有效性需要各自线程负责
*/
public synchronized Connection getConnection() {
Connection con = null;
if (pool.size() > 0) {
// 获取向量中第一个可用连接
con=(Connection)pool.remove(0);
if (pool.size() < minConn) {
//小于最小连接数时,触发获取连接的线程操作
if (!addThreadFlag) {
addThreadFlag = true;
Thread thread = new Thread(new AddConnectionProcess(this));
thread.start();
}
}
} else {
try {
con = dbSource.newConnection();
} catch (Exception e) {
e.printStackTrace();
}
}
return con;
}
//释放连结
public synchronized void release() {
Enumeration allConnections = pool.elements();
while (allConnections.hasMoreElements()) {
Connection con = (Connection) allConnections.nextElement();
try {
con.close();
}catch (SQLException e) {
e.printStackTrace();
}
}
pool.removeAllElements();
}
public int getNormalConn() {
return normalConn;
}
public String getName() {
return name;
}
public int getMinConn() {
return minConn;
}
public Vector getPool() {
return pool;
}
public boolean getAddThreadFlag() {
return addThreadFlag;
}
public void setAddThreadFlag(boolean addThreadFlag) {
this.addThreadFlag = addThreadFlag;
}
public DbSource getDbSource() {
return dbSource;
}
}
//创建连接线程类
public class AddConnectionProcess implements Runnable{
private ConnectionPool connectionPool;
public AddConnectionProcess(ConnectionPool pool){
this.connectionPool =pool;
}
//更新到最大连接数
public void run() {
System.out.println("running add connection");
Vector conns=new Vector();
int num=connectionPool.getNormalConn()-connectionPool.getPool().size();
try{
while(num>0){
Connection conn= connectionPool.getDbSource().newConnection();
if(conn!=null){
//conn.setAutoCommit(false);
//conn.setReadOnly(true);
conns.add(conn);
num--;
}
}
}catch(Exception e){
try{
Thread.sleep(60*1000);
}catch(Exception e2){
e2.printStackTrace();
}
}
Vector pool=connectionPool.getPool();
pool.addAll(conns);
connectionPool.setAddThreadFlag(false);
}
}
//数据库连接接口
public interface DbSource {
public Connection newConnection() throws Exception;
}