해쉬코드를 키값으로 하는 DBConnection Pool을 한번 만들어 보았다..
/**
* <p>Title: ConnectionPool</p>
* <p>Description: ConnectionPool</p>
* <p>Copyright: Copyright (c) 2005 Maxoft.Inc</p>
* <p>Company: Maxoft.Inc </p>
* @author Kim sooki
* @version 1.0
*/
package net.maxoft.center.controller;
import com.mysql.jdbc.Statement;
import java.io.*;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.*;
import net.maxoft.model.GlobalsFactory;
import org.apache.log4j.Logger;
public class ConnectionPool extends Thread {
public static synchronized ConnectionPool getInstance(){
if(instance == null){
instance = new ConnectionPool();
}
return instance;
}
private ConnectionPool() {
use = 0;
close = false;
available = 0;
pool = new HashMap();
keyMap = new HashMap();
try{
makeConnections();
}catch(Exception e){
e.printStackTrace();
running = false;
logger.debug(“Connection pool create fail!!”);
}
logger.info(“Connection Pool created!!”);
}
private void makeConnections() throws SQLException{
for(int i = 0 ; i < ConnectionPool.MAX_ALIVE; i++){
try{
Class.forName(GlobalsFactory.getGlobals().getProperty(“jdbcDriverClass”)).newInstance();
String URL = GlobalsFactory.getGlobals().getProperty(“jdbcConnectionUrl”);
Connection connection = DriverManager.getConnection(URL,”root”,”****”);
int hash = connection.hashCode();
pool.put(new Integer(hash), connection);
keyMap.put(new Integer(hash), new Integer(hash));
logger.debug(“Make connection : “+ connection + ” / ” + hash + ” / ” + available);
available++;
}catch(Exception e){
e.printStackTrace();
}
}
if( pool.size() == 0){
throw new SQLException(“Create fail Connection!!!”);
}
logger.debug(“Connection : ” + available + ” created!”);
}
private Connection addConnection() throws SQLException {
try{
Class.forName(GlobalsFactory.getGlobals().getProperty(“jdbcDriverClass”)).newInstance();
String URL = GlobalsFactory.getGlobals().getProperty(“jdbcConnectionUrl”);
Connection connection = DriverManager.getConnection(URL,”root”,”****”);
logger.debug(connection);
return connection;
}catch(Exception e){
e.printStackTrace();
throw new SQLException(“Connection create fail!”);
}
}
private void closeAllConnection(){
Iterator iter = pool.keySet().iterator();
while(iter.hasNext()){
Integer hash = (Integer)iter.next();
Connection con = null;
try{
con = (Connection)pool.remove(hash);
con.close();
available–;
}catch(Exception e){
e.printStackTrace();
}finally {
if(con != null){
try{
con.close();
}catch(Exception e){
} // inner try – catch;
} // if(con != null)
} // outter try – catch;
} // while – iterator
logger.debug(“Connection all closed!!”);
}
protected void finalize() throws Throwable {
if(close != false){
close();
}
super.finalize();
}
public synchronized void close(){
if(close == true)
return;
close = true;
closeAllConnection();
pool = null;
}
public synchronized void releaseConnection(Connection con) throws SQLException {
if(con == null){
throw new SQLException(“Connection is null!!”);
}
synchronized(pool){
int hash = con.hashCode();
if(keyMap.containsKey(new Integer(hash))){
pool.put(new Integer(hash), con);
available++;
use–;
} else {
try{
con.close();
}catch(Exception e){
logger.debug(“Close connection error!”);
e.printStackTrace();
throw new SQLException(“Close connection error!”);
}
}
}
}
public synchronized Connection getConnection() throws SQLException {
if(use > 50){
throw new SQLException(“MAX Connection Alive!!”);
}
synchronized(pool){
if(pool.size() > 0){
Iterator iter = pool.keySet().iterator();
if(!iter.hasNext())
logger.debug(“key not exist!!”);
Integer hash = (Integer)iter.next();
Connection con = (Connection)pool.remove(hash);
available–;
use++;
return con;
}
}
return addConnection();
}
public void run(){
// 시간마다 avaliable connection의 상태를 점검
// 연결이 닫혔으면 map에서 삭제하고 다시 연결한뒤 저장
// Connection에러가 발생하여 0개의 conn이 유효한경우 종료
// running = false 인경우 종료
}
private Connection con;
private boolean running = true;
private static final int MAX_ALIVE = 10;
private int available;
private int use;
private HashMap pool;
private HashMap keyMap;
private static ConnectionPool instance;
private boolean close;
private static final Logger logger;
static
{
logger = Logger.getLogger(net.maxoft.center.controller.ConnectionPool.class);
}
}
Connection Pool 자체를 Thread로 설정하여 일정주기동안 Managed connection의 validate를 check 하도록 추가해 주어야 한다.
MAX_ALIVE의 갯수를 넘어서는 Connection요청은 Connection을 생성후 반납시 close()하도록 되어 있다.
드라이버이름과 URL은 Pref를 구현한 클래스로부터 얻어오도록 되어 있으므로 Prefs를 직접구현하도록 한다.