日期:2014-05-16 浏览次数:20596 次
在服务器端涉及数据库访问的应用程序里头,数据库连接池是一项确保性能的关键技术。一谈起java数据库连接池,大家都可以罗列出一堆开源实现。
它们也各有优劣:
1. DBCP  TOMCAT自带的
2. proxool
3. c3p0: see: http://sourceforge.net/projects/c3p0
4. DBPool
5. Taobao的druid
这些都是蛮不错的连接池实现。基于不用重复造轮子一说,完全可以挑一个自己喜欢的去用。已有的轮子如果没出问题,还好说,出了问题,往往很难解决。
本文的主旨是阐述连接池的基本思想:
1. 能将池化的资源(连接)控制在一定范围以内[min, max]
2. 能在jvm退出之前,释放这些连接资源
3. 能尽量简化用户的代码
4. 能确保连接池的连接始终是活跃的
下面还是上代码吧, 以下的代码是整理而成,缺点还是不少,但是也足够一般情况下的使用,至少是可控的。
1.  一个hook类,用于jvm退出前释放资源
package com.hisql;
import java.sql.SQLException;
import org.apache.log4j.Logger;
public class ReleasePoolHook implements Runnable
{
    public static final Logger logger = Logger.getLogger(ReleasePoolHook.class);
    ConnectionPool connpool;
    public ReleasePoolHook(ConnectionPool pool)
    {
        // register it
        connpool = pool;
        Runtime.getRuntime().addShutdownHook(new Thread(this));
        logger.info(">>> shutdown hook registered...");
    }
    
    @Override
    public void run()
    {
        // TODO Auto-generated method stub
        logger.info("\n>>> About to execute: " + ReleasePoolHook.class.getName() + ".run() to clean up before JVM exits."); 
        this.cleanUp(); 
        logger.info(">>> Finished execution: " + ReleasePoolHook.class.getName() + ".run()"); 
    }
    
    private void cleanUp()
    {
        if (connpool != null)
        {
            try
            {
                connpool.closeConnectionPool();
                logger.info("Pool realeased....");
            }
            catch (SQLException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
                logger.warn("Pool released with exception", e);
            }
            
        }
    }
}
package com.hisql;
import java.sql.Connection;
public class PooledConnection
{
    Connection connection = null;
    boolean busy = false;
    
    public PooledConnection(Connection connection)
    {
        this.connection = connection;
    }
    
    public Connection getConnection()
    {
        return connection;
    }
    
    public void setConnection(Connection connection)
    {
        this.connection = connection;
    }
    
    public boolean isBusy()
    {
        return busy;
    }
    
    public void setBusy(boolean busy)
    {
        this.busy = busy;
    }
}这是主体实现类:
package com.hisql;
import java.sql.*;
import java.util.*;
import org.apache.log4j.Logger;
public class ConnectionPool
{
    private String jdbcDriver;
    private String dbUrl;
    private String dbUsername;
    private String dbPassword;
    private String pingSql = "select 1"; // the test sql statement to ping the target database
    private int minConnections = 5;
    private int incrementalConnections = 2;
    private int maxConnections = 20;
    
    private Vector<PooledConnection> connections;
    private ReleasePoolHook hook;
    
    public static final Logger logger = Logger.getLogger(ConnectionPool.class);
    
    public ConnectionPool(String driver, String url, String username, String password)
    {
        jdbcDriver = driver;
        dbUrl = url;
        dbUsername = username;
        dbPassword = password;
        hook = new ReleasePoolHook(this);
    }
    
    public int getInitialConnections()
    {
        return this.minConnections;
    }
    
    public void setInitialConnections(int initialConnections)
    {
        this.minConnections = initialConnections;
    }
    
    public int getIncrement