随笔-71  评论-4  文章-0  trackbacks-0
通常商业数据库JDBC驱动都会提供自已的数据库连接池管理器,无需自己制做。
无论如何,这里给出一个简单实现

实现连接池的关键点:
1. 单实例
2. 由实现类来管理数据库连接,包括连接,刷新
3. 重载java.sql.Connection的close功能。当客户程序调用close时不是真正的断开连接,而是将连接归还连接池管理器。
4. 将数据库属性独立于管理器本身

可选:
1. 实现javax.sql.PooledConnection
2. 实现javax.sql.DataSource
3. 实现javax.sql.ConnectionPoolDataSource

一个简单实现:
import java.io.*;
import java.util.*;
import java.sql.*;

public class ConnectionPool implements Runnable {
    static String configFileName; // 如./connection-pool.properties
    static Properties config;
private static List list = null;
    private static boolean isCreate = false;
    /**
     * 实现单实例,关键点1
     * @throws SQLException
     */
public ConnectionPool () throws SQLException {
if (list == null) init ();
        if (!isCreate) {
            Thread thread = new Thread(this);
            thread.run();
            isCreate = true;
        }
}

    public synchronized Connection getConnection () {
        if (list == null) return null;

        // 寻找空闲的连接
        for (int i = 0; i < list.size(); i ++){
            ConnectionWrap conn = (ConnectionWrap)list.get(i);
            if (conn.free) {
                conn.free = false;
                conn.start = System.currentTimeMillis();
                return conn;
            }
        }

        // 没有空闲的连接则自动扩展
        int step = Integer.parseInt(config.getProperty("step")); // 取得自动扩展的步长
        this.addConnection(step);
            return (ConnectionWrap)list.get(list.size() - step - 1);
    }

    public void run () {
        long interval = Long.parseLong(config.getProperty("interval")); // 扫描时间
        while (true) {
            try {
                Thread.sleep(interval);
            } catch (Exception e) {
                // 出错处理
            }
            scan ();
        }
    }

    /**
     * 关键点2,管理连接。一些超时的连接刷新
     */
    private void scan () {
        int timeout = Integer.parseInt(config.getProperty("timeout"));
        for (int i = 0; i < list.size(); i ++) {
            ConnectionWrap conn = (ConnectionWrap) list.get(i);
            if (conn.start >; 0) {
                time = System.currentTimeMillis() - conn.start;
                if (time >;= timeout)
                    conn.close();
            }
        }

        int initCount = Integer.parseInt(config.getProperty("init-count"));
        if (list.size() >;  initCount) { // 恢复到初始连接数
            for (int i = list.size() - 1; i >; initCount; i --) {
                ConnectionWrap conn = (ConnectionWrap) list.get(i);
                if (conn.free) { // 真正地断开连接
                    try {
                        conn.conn.close();
                    } catch (SQLException ignore){}
                    list.remove(conn);
                }
            }
        }
    }

private void init () throws SQLException {
config = readConfig ();
createConnectionPool (config);
}

    /**
     * 读取配置文件
     * @return java.util.Properties
     * @throws SQLException
     */
private void readConfig () throws SQLException {
InputStream in = null;
        try {
            in = new FileInputStream (configFileName);
            config = new Properties ();
            config.load(in);
        } catch (IOException ioe) { // 出错处理
            throw new SQLException (ioe.getMessage());
        } finally {
            if (in != null)
                try { in.close(); } catch (IOException ignore) {}
        }
}

    private void createConnectionPool () throws SQLException {
        String driverName = config.getProperty("driver-name");

        int initCount = Integer.parseInt(config.getProperty("init-count"));
        int maxCount = Integer.parseInt(config.getProperty("max-count"));
        try {
            Driver driver = Class.forName(driverName);
            addConnection (initCount);
        } catch (Exception e) {
            throw new SQLException (e.getMessage());
        }
    }

    private void addConnection (int count) throws SQLException {
        if (list == null) list = new ArrayList (count);
        String url = config.getProperty("url");
        String user = config.getProperty("user");
        String password = config.getProperty("password");

        for (int i = 0; i < count; i ++)
            list.add(new ConnectionWrap (url, user, password));
    }

    class ConnectionWrap implements Connection {
        Connection conn = null;
        boolean free;
        long start;
        ConnectionWrap (String url, String user, String password) throws Exception {
            Connection conn = DriverManager.getConnection(url, user, password);
            free = true;
        }

        /**
         * 这里关键点3,并不真正断开连接,而是归还给管理器
         * @return
         * @throws SQLException
         */
        public boolean close () throws SQLException {
            free = true;
            start = 0;
        }

        // 其他java.sql.Connection的方法
        // ...
    }
}

配置文件示例
driver-name = oracle.jdbc.driver.Driver
url = jdbc:oracle:thin:@host:1521:employee
user = scott
password = tiger
timeout = 60000 # 一分钟
init-count = 10
step = 5
interval = 1000 # 1秒
...

以后在客户端可以这么调用
ConnectionPool pool = new ConnectionPool ();
Connection conn = null;
try {
conn = pool.getConnection ();
// 其他操作
} finally {
if (conn != null) conn.close ();
}

限于篇幅,javax.sql.DataSource, javax.sql.ConnectionPoolDataSource等就不一一列出了
posted on 2006-06-06 20:36 zjw_albert 阅读(259) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: