日期:2014-05-16  浏览次数:20650 次

对数据库连接池的一些修改

上次写的连接池一旦得不到连接就返回null,个人觉得很不合理。稍微改了一下,增加了等待时间。另外,连接池的容量改成了缓慢增加,而不是一下子就翻一倍。

ConnectionPool.java

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import java.util.Vector;

public class ConnectionPool {

    private Vector<Connection> pool;

    private String url;

    private String username;

    private String password;

    private String driverClassName;
    /** 
     * 请求连接的等待时间限制
     */
    private long timeout;
    /** 
     * 连接池的大小,也就是连接池中有多少个数据库连接。
     */
    private int poolSize;
    
    private int poolSizeMax;

    private static ConnectionPool instance = new ConnectionPool();

    private ConnectionManager connectionManager;
    /** 
     * 私有的构造方法,禁止外部创建本类的对象,要想获得本类的对象,通过<code>getIstance</code>方法。
     * 使用了设计模式中的单子模式。
     */
    private ConnectionPool() {
        init();
    }

    /** 
     * 连接池初始化方法,读取属性文件的内容 建立连接池中的初始连接
     */
    private void init() {
        pool = new Vector<Connection>();
        readConfig();
        initConnection(poolSize);  //初始化最小的线程数
        connectionManager = new ConnectionManager(pool,poolSize);
        connectionManager.start();
    }

    /** 
     * 返回连接到连接池中
     */
    public synchronized void release(Connection conn) {
        pool.add(conn);
        notifyAll();//通知所有等待连接的线程
    }

    /** 
     * 关闭连接池中的所有数据库连接
     */
    public synchronized void closePool() {
        for (int i = 0; i < pool.size(); i++) {
            try {
                ((Connection) pool.get(i)).close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            pool.remove(i);
        }
    }

    /** 
     * 返回当前连接池的一个对象
     */
    public static ConnectionPool getInstance() {
        return instance;
    }

    /** 
     * 返回连接池中的一个数据库连接 
     */
    public synchronized Connection getConnection() {
    	Connection conn =null;
		try {
			conn = getConnection(timeout);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return conn;
		
    }
    
    /** 
     * 返回连接池中的一个数据库连接
     * @throws SQLException 
     */
    private Connection getConnection(long timeout) throws SQLException  {
    	long startTime = System.currentTimeMillis();
    	long remaining = timeout;
    	Connection conn = null;
    	while((conn=getPooledConnection()) == null){
    		try {
				wait(remaining);//没有可用的链接,线程等待,直到超时或其它线程调用了notifyAll
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			remaining = timeout - (System.currentTimeMillis() - startTime);
    		if(remaining<=0){  //超时则抛出异常
    			throw new SQLException("getConnection() timeout");
    		}
    	}
    	//如果无异常抛出,则获得了一个连接,现测试该连接是否可用
    	if(!isConnectionOK(conn)){
    		return getConnection(remaining);
    	}
		return conn;
	}

	/** 
     * 测试连接是否真正是可用的
     */
    private boolean isConnectionOK(Connection conn) {
		Statement stmt = null;
		try{
			if(!conn.isClosed()){
				stmt = conn.createStatement();
				stmt.close();
			}
			else{
				return false;
			}
		}
		catch(SQLException e){
			if(stmt!=null){
				try{
					stmt.close();
				}
				catch(SQLException se){		
				}	
			}
			return false;
		}
		return true;
	}

	/** 
     * 在连接池中创建初始设置的的数据库连接
     */
    private void initConnection(int size) {
        Connection conn = null;
        for (int i = 0; i < size; i++) {

            try {
                Class.forName(driverClassName);
                conn = java.sql.DriverManager.getConnection(url, username, password);
                pool.add(conn);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }
    }
    
    private Connection getPooledConnection(){
    	Connection conn = null;
    	if(pool.size()>0){
    		conn = pool.remove(0);
    	}
    	else if(pool