数据源连接池



import com.tanghd.main.config.ConfigPO;
import com.tanghd.utils.NumberUtils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Semaphore;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 数据库连接池
 */
public class ConnectionPool {

    /**
     * 单实例
     */
    private static ConnectionPool instance = new ConnectionPool();
    public static Log log = LogFactory.getLog(ConnectionPool.class);
    /**
     * 用于保存数据库连接
     */
    private static ConcurrentLinkedQueue<Connection> pool = new ConcurrentLinkedQueue<Connection>();
    /**
     * 保存当前被使用中是连接
     */
    private static BlockingQueue<Connection> using = null;
    /**
     * 信号量,控制最多多少个请求同时能获取到连接
     */
    private static Semaphore position;
    /**
     * 最大连接数
     */
    private static int MAX = 30;
    /**
     * 初始化连接数
     */
    private static int INIT = 15;
    /**
     * 数据库连接URL
     */
    private static String url;
    /**
     * 数据库连接用户名
     */
    private static String user;
    /**
     * 数据库连接密码
     */
    private static String password;
    /**
     * 数据库连接驱动
     */
    private static String driver;
    private static long connectionColloctPeriod = 0;
    private static Timer cleanTask;
    
    public static ConnectionPool getInstance() {
        return instance;
    }

    /**
     * 初始化,应用启动时调用
     *
     * @throws Exception
     */
    public synchronized static void init() throws Exception {
        initParameters();
        initPool();
        position = new Semaphore(MAX);
    }

    /**
     * 从连接池中获取连接,如果为空,则新建连接 由于有信号量控制,所以不检查当前生成的连接是否已达到最大限制
     *
     * @return
     * @throws Exception
     */
    public Connection getConnection() throws Exception {
        position.acquire();
        Connection conn = pool.poll();
        if (null == conn) {
            log.debug("create a new connnection ");
            conn = createNewConnection();
        } else {
            log.debug("use an old connnection ");
        }
        ConnectionWapper tmpConn = (ConnectionWapper) conn;
        tmpConn.setIsInPool(false);
        using.add(conn);
        return conn;
    }

    /**
     * 关闭连接,并返回连接池中
     *
     * @param conn
     */
    public void closeConnection(ConnectionWapper conn) {
        if (null != conn) {
            try {
                conn.commit();
                if (!conn.isClosed()) {
                    pool.add(conn);
                    ConnectionWapper tmpConn = (ConnectionWapper) conn;
                    tmpConn.setIsInPool(true);
                    tmpConn.setLastUseTime(System.currentTimeMillis());
                    using.remove(conn);
                }
            } catch (Exception e) {
                log.error(e);
            }
            log.debug("release a connection into pool.");
            position.release();
        }
    }

    /**
     * 初始化连接池,预先生成
     *
     * @throws Exception
     */
    private static void initPool() throws Exception {
        List<Connection> tmpArray = new ArrayList<Connection>(INIT);
        for (int i = 0; i < INIT; i++) {
            tmpArray.add(instance.createNewConnection());
        }
        pool.addAll(tmpArray);
        tmpArray = null;
        using = new ArrayBlockingQueue<Connection>(MAX+INIT);
        if (connectionColloctPeriod > 0) {
            cleanTask = new Timer();
            cleanTask.schedule(new ConnectionCollector(ConnectionPool.getInstance(), connectionColloctPeriod), connectionColloctPeriod, connectionColloctPeriod);
        }
    }

    /**
     * 加载参数
     */
    private static void initParameters() {
        url = ConfigPO.getConfig("db_url");
        user = ConfigPO.getConfig("db_user");
        password = ConfigPO.getConfig("db_pwd");
        driver = ConfigPO.getConfig("db_driver");
        
        MAX = NumberUtils.parseInteger(ConfigPO.getConfig("db_max_connections"), 30);
        INIT = NumberUtils.parseInteger(ConfigPO.getConfig("db_init_connections"), 15);
        connectionColloctPeriod = NumberUtils.parseLong(ConfigPO.getConfig("db_clean_connections_period"), 0);
    }

    /**
     * 新建连接
     *
     * @return
     * @throws Exception
     */
    private Connection createNewConnection() throws Exception {
        ConnectionWapper conn = null;
        try {
            Class.forName(driver).newInstance();
            Connection con = DriverManager.getConnection(url, user, password);
            conn = new ConnectionWapper(con);
        } catch (Exception ex) {
            log.error(ex);
            throw ex;
        }
        return conn;
    }
    
    public void clearOldConnections(long period) {
        long current = System.currentTimeMillis();
        synchronized (pool) {
            Iterator<Connection> iter = pool.iterator();
            while (iter.hasNext()) {
                ConnectionWapper conn = (ConnectionWapper) iter.next();
                if (conn.isIsInPool()) {
                    if (conn.getLastUseTime() - current > period) {
                        try {
                            conn.getConn().close();
                        } catch (Exception e) {
                            log.error(e);
                        }
                        iter.remove();
                        log.info("remove an old connection");
                    }
                }
            }
        }
    }
}


import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Savepoint;
import java.sql.Statement;
import java.util.Map;

/**
 * 数据库连接
 */
public class ConnectionWapper implements Connection {

    /**
     * 数据库连接
     */
    private Connection conn;
    /**
     * 是否在连接池里,如果是true,调用该连接的时候,会抛出异常
     */
    private boolean isInPool;
    /**
     * 最后一次调用放入连接池的时间
     */
    private long lastUseTime;

    public Connection getConn() {
        return conn;
    }

    public boolean isIsInPool() {
        return isInPool;
    }

    public void setIsInPool(boolean isInPool) {
        this.isInPool = isInPool;
    }

    public long getLastUseTime() {
        return lastUseTime;
    }

    public void setLastUseTime(long lastUseTime) {
        this.lastUseTime = lastUseTime;
    }

    private void checkPooling() throws SQLException {
        if (isInPool) {
            throw new SQLException("已关闭的连接");
        }
    }

    public void close() throws SQLException {
        ConnectionPool.getInstance().closeConnection(this);
    }

    public ConnectionWapper(Connection conn) {
        this.conn = conn;
    }

    public Statement createStatement() throws SQLException {
        checkPooling();
        return this.conn.createStatement();
    }

    public PreparedStatement prepareStatement(String sql) throws SQLException {
        checkPooling();
        return this.conn.prepareStatement(sql);
    }

    public CallableStatement prepareCall(String sql) throws SQLException {
        checkPooling();
        return this.conn.prepareCall(sql);
    }

    public String nativeSQL(String sql) throws SQLException {
        checkPooling();
        return this.conn.nativeSQL(sql);
    }

    public void setAutoCommit(boolean autoCommit) throws SQLException {
        checkPooling();
        this.conn.setAutoCommit(autoCommit);
    }

    public boolean getAutoCommit() throws SQLException {
        checkPooling();
        return this.conn.getAutoCommit();
    }

    public void commit() throws SQLException {
        checkPooling();
        this.conn.commit();
    }

    public void rollback() throws SQLException {
        checkPooling();
        this.conn.rollback();
    }

    public boolean isClosed() throws SQLException {
        checkPooling();
        return this.conn.isClosed();
    }

    public DatabaseMetaData getMetaData() throws SQLException {
        checkPooling();
        return this.conn.getMetaData();
    }

    public void setReadOnly(boolean readOnly) throws SQLException {
        checkPooling();
        this.conn.setReadOnly(readOnly);
    }

    public boolean isReadOnly() throws SQLException {
        checkPooling();
        return this.conn.isReadOnly();
    }

    public void setCatalog(String catalog) throws SQLException {
        checkPooling();
        this.conn.setCatalog(catalog);
    }

    public String getCatalog() throws SQLException {
        checkPooling();
        return this.conn.getCatalog();
    }

    public void setTransactionIsolation(int level) throws SQLException {
        checkPooling();
        this.conn.setTransactionIsolation(level);
    }

    public int getTransactionIsolation() throws SQLException {
        checkPooling();
        return this.conn.getTransactionIsolation();
    }

    public SQLWarning getWarnings() throws SQLException {
        checkPooling();
        return this.conn.getWarnings();
    }

    public void clearWarnings() throws SQLException {
        checkPooling();
        this.conn.clearWarnings();
    }

    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
        checkPooling();
        return this.conn.createStatement(resultSetType, resultSetConcurrency);
    }

    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
        checkPooling();
        return this.conn.prepareStatement(sql, resultSetType, resultSetConcurrency);
    }

    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
        checkPooling();
        return this.conn.prepareCall(sql, resultSetType, resultSetConcurrency);
    }

    public Map<String, Class<?>> getTypeMap() throws SQLException {
        checkPooling();
        return this.conn.getTypeMap();
    }

    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
        checkPooling();
        this.conn.setTypeMap(map);
    }

    public void setHoldability(int holdability) throws SQLException {
        checkPooling();
        this.conn.setHoldability(holdability);
    }

    public int getHoldability() throws SQLException {
        checkPooling();
        return this.conn.getHoldability();
    }

    public Savepoint setSavepoint() throws SQLException {
        checkPooling();
        return this.conn.setSavepoint();
    }

    public Savepoint setSavepoint(String name) throws SQLException {
        checkPooling();
        return this.conn.setSavepoint(name);
    }

    public void rollback(Savepoint savepoint) throws SQLException {
        checkPooling();
        this.conn.rollback(savepoint);
    }

    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
        checkPooling();
        this.conn.releaseSavepoint(savepoint);
    }

    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        checkPooling();
        return this.conn.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
    }

    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        checkPooling();
        return this.conn.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
    }

    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        checkPooling();
        return this.conn.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
    }

    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
        checkPooling();
        return this.conn.prepareStatement(sql, autoGeneratedKeys);
    }

    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
        checkPooling();
        return this.conn.prepareStatement(sql, columnIndexes);
    }

    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
        checkPooling();
        return this.conn.prepareStatement(sql, columnNames);
    }
}

你可能感兴趣的:(连接池)