package chars.pool;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import COM.ibm.db2.jdbc.app.DB2Driver;

/**
 * JDK version used : jdk1.4.2_07 <br>
 * Description : 一個數據庫連接池的實現 <br>
 * Comments Name : CharsConnectionPool <br>
 * author :chars <br>
 * date :2007-06-11<br>
 * Version : 1.00 <br>
 */
public class CharsConnectionPool
{
   //---------------連接數據庫所需要的元素---------------
 private String driver;

 private String url;

 private String userName;

 private String password;

  //----------------------------------------------
 private List connections = null;//連接池的容器

 private  int intiateCount = 10;// 初始化連接數

 private  int maxCount = 100;// 連接池可以產生的最大連接數

 private  int rateCount = 10;// 連接不夠時一次可以申請的連接數
 
 public static int ACTIVE_ACOUNT = 0;//記錄目前的活動連接數

 public String getDriver()
 {
     return driver;
 }

 public void setDriver(String driver)
 {
     this.driver = driver;
 }

 public int getIntiateCount()
 {
     return intiateCount;
 }

 public void setIntiateCount(int intiateCount)
 {
     this.intiateCount = intiateCount;
 }

 public int getMaxCount()
 {
     return maxCount;
 }

 public void setMaxCount(int maxCount)
 {
     this.maxCount = maxCount;
 }

 public String getPassword()
 {
     return password;
 }

 public void setPassword(String password)
 {
     this.password = password;
 }

 public int getRateCount()
 {
     return rateCount;
 }

 public void setRateCount(int rateCount)
 {
     this.rateCount = rateCount;
 }

 public String getUrl()
 {
     return url;
 }

 public void setUrl(String url)
 {
     this.url = url;
 }

 public String getUserName()
 {
     return userName;
 }

 public void setUserName(String userName)
 {
     this.userName = userName;
 }
    /**
     * 連接池構造函數
     * @param driver
     * @param url
     * @param userName
     * @param password
     * @param connections
     */
 public CharsConnectionPool(String driver, String url, String userName, String password)
 {
    super();
    this.driver = driver;
    this.url = url;
    this.userName = userName;
    this.password = password;
 }
 
 public CharsConnectionPool(Properties p)
 {
    super();
    this.driver = p.getProperty("driver");
    this.url =  p.getProperty("url");
    this.userName = p.getProperty("userName");
    this.password = p.getProperty("password");
 }

 /**
  * 初始化連接池
  *
  */
 public void initiatePools()throws Exception
 {
     if (connections != null)return;//如果連接池已經建立則不再次進行初始化
  
     connections = new ArrayList();
     initParamters();//根據數據庫支持的最大連接數配置該連接池的相關參數.
     for (int i = 0; i < intiateCount; i++){
     connections.add(newCharsConnection());
  }
 }
 /**
  * 銷毀連接池
  * @throws Exception
  */
 public void destoryPools()throws Exception
 {
     if (connections == null) return ;
     for(int i=0; i<connections.size();i++){
     CharsPoolConnection conn = (CharsPoolConnection)connections.get(i);
   
     if(conn.isBusy()) Thread.sleep(5000);//如果該連接正在使用則再給5秒時間
     closeConnection(conn.getConnection());
     connections.remove(conn);
  }
  connections = null;
 }
    /**
     * 從連接池獲取連接
     *
     */
 public Connection getConnection()throws SQLException
 {
        Connection conn = null;
        try{
         
         conn = getFreeConnection();        
         if(conn == null) {
           Thread.sleep(3000);//暫停3秒鐘再試著獲取連接
           conn = getFreeConnection();
         }       
         if(conn == null) {//此時如果還不能獲得連接則表示,連接池中的連接已經用完
          throw new SQLException("連接池連接連接使用枯竭,請稍后再試!!");
         }
        }catch(Exception e)
        {
         e.printStackTrace();
        }
        return conn;
 }
    /**
     * 歸還連接到連接池(當連接用完時)
     * @param conn
     */
 public void rebackConnection(Connection conn)
 {
           for(int i = 0;i < connections.size();i++){
            CharsPoolConnection charsCon = (CharsPoolConnection)connections.get(i);
            if(charsCon.getConnection() == conn){
             charsCon.setBusy(false);
             conn = null;//外部引用為空.
             ACTIVE_ACOUNT --;
             break;
            }
           }
 }
   
 // ---------------------------------------------------------------------------------------------------
    /**
     * 加載驅動程序,配置實際上可以用的最大連接數
     */
 private void initParamters() throws Exception
 {
    int realMaxCount = -1;
   Connection con = null;
   try
  {
      Driver driver1 = new DB2Driver();
      DriverManager.registerDriver(driver1);   
      con = DriverManager.getConnection(this.url, this.userName, this.password);   
      DatabaseMetaData dmd = con.getMetaData();
      realMaxCount = dmd.getMaxConnections();
   
     if(realMaxCount == 0){//如果返回的值為0,則表示最大的連接數不受限制
      realMaxCount = 1000;//那么默認賦一個較大的值給它
   }
  }
  finally{
     if(con == null) con.close();
  }
  
  if(realMaxCount < intiateCount) {//如果數據庫允許的最大活動連接數小于初始化的連接數
    intiateCount = maxCount;     //則實際上初始化的連接數應該等于數據庫允許的最大活動連接數據
    maxCount = realMaxCount;
  }
  else if(intiateCount < realMaxCount && maxCount >= realMaxCount){//如果數據庫最大的活動連接數大于初始化連接數但是小于該連接池允許的最大連接數
    maxCount = realMaxCount;                                     //則該池的最大連接數等于數據庫允許的最大活動連接數
  }
 }
 /**
  * 獲取可以用的連接,如果沒有查找到則根據條件在池中加入新的連接
  * @return
  * @throws SQLException
  */
 private Connection getFreeConnection()throws SQLException
 {
     Connection conn = null;
     conn = findFreeConnection();//首先到連接池中找空閑的連接
     if(conn == null){//如果沒有找到,則試著產生新的連接放入池中
     for(int i = 1; connections.size() < maxCount && i <= rateCount;i++){//是否再能在連接池中增加連接取決與maxCount
     connections.add(newCharsConnection());
    }
    conn = findFreeConnection();//再次在連接池中找
  }  
   return conn;
 }
 /**
  * 在池中查找可以使用的連接
  * @return
  */
 private Connection findFreeConnection()throws SQLException
 {
     CharsPoolConnection charsConn = null;
     Connection conn = null;
     for(int i = 0; i < connections.size();i++){
     charsConn = (CharsPoolConnection)connections.get(i);
     if(charsConn.isBusy())continue;
     else {
         if(!isAvalidConnection(charsConn.getConnection())) {
          charsConn.setConnection(newConnection());
          }
      conn = charsConn.getConnection();//得到可以用的連接
      charsConn.setBusy(true);//表明為使用狀態
      ACTIVE_ACOUNT++;
      break;
      }
    }
    return conn;
 }
 
 /**
  * 判斷池中的連接是否因為其他原因變得不可以用
  * @param conn
  * @return
  */
 private boolean isAvalidConnection(Connection conn)
 {
    try
    {
         conn.setAutoCommit(true);//模擬動作,如果能夠能夠操作則說明該連接可用
     }catch(SQLException e)
    {
       closeConnection(conn);
       return false;
    }
    return true;
 }
 
 /**
  * 判斷一個連接是否還可以用,如果不可以用則創建一個新的連接代替它
  * @param conn
  * @return
  */
 private CharsPoolConnection newCharsConnection()throws SQLException
 {
  
     CharsPoolConnection charsCon = new CharsPoolConnection();
     charsCon.setConnection(newConnection());
     charsCon.setBusy(false);
  
     return charsCon;
 }
 /**
  * 獲取一個新的數據庫連接
  * @return
  * @throws SQLException
  */
 private Connection newConnection()throws SQLException
 {
      return DriverManager.getConnection(this.url,this.userName,this.password);
 }
 /**
  * 關閉數據庫連接
  * @param conn
  */
 private void closeConnection(Connection conn)
 {
  try
  {
       conn.close();
  }catch(SQLException se)
  {
      System.out.println("關閉連接發生異常...");
  }
 }
}


封裝連接池的連接:
package chars.pool;

public class CharsPoolConnection
{
    private boolean isBusy;
   
    private java.sql.Connection connection;

   public java.sql.Connection getConnection()
  {
       return connection;
  }

  public void setConnection(java.sql.Connection connection)
 {
      this.connection = connection;
 }

 public boolean isBusy()
 {
      return isBusy;
 }

 public void setBusy(boolean isBusy)
 {
      this.isBusy = isBusy;
 }
}

調用的方式大致可以這樣:
    CharsConnectionPool pool = new CharsConnectionPool(env);
     pool.initiatePools();
    Connection conn= pool.getConnection(); //獲取連接
    //do something with your code;
    pool .rebackConnection(conn); 歸還連接到連接池