JDBC连接池的简单实现

来源:互联网 发布:张民弢 知乎 编辑:程序博客网 时间:2024/06/05 02:56

先说明一下,我本身是做android开发的,java web是我的弱项,只是近来京东云免费,于是去折腾了几下,有了些许经验,特作分享。如果文章中内容有误,还请各高手指正。

我在web端,需要连接数据库进行查询插入等操作,但是每次进行操作都先获取连接用完后就断开的话,未免效率太低。以前知道tomcat中可以配置,但是京东云引擎的tomcat并不能由自己配置。因为我折腾的东西较小,所以也不考虑使用框架,于是就想自己写一个。

我写的连接池很简单,在初始化时创建5个连接,并放在一个列表当中。如果要获取连接,从列表中获取,同时列表移除,还回来时,列表添加上。也就是列表保存的是闲置的连接。

如果列表已经为空了,那么判断是否超过最大连接了,没有就创建,有的话就等待。当然,我这里做的是很简单的实现,所以没有去做等待超时等处理。

代码如下:

package com.githang.tucao.web.dbc;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.sql.Statement;import java.util.LinkedList;public class DatabaseConnection {    private static final String CREATE_TABLE_TWITTER = "CREATE TABLE IF NOT EXISTS twitter (id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, msg varchar(300) not null) DEFAULT CHARSET=utf8";    final static String HOST = "host";    final static String PORT = "port";    final static String DB_NAME = "dbname";    final static String USERNAME = "username";    final static String PASSWORD = "password";    final static String url = "jdbc:mysql://" + HOST + ":" + PORT + "/" + DB_NAME            + "?useUnicode=true&characterEncoding=utf-8";    private static final DatabaseConnection instance = new DatabaseConnection();    private final int INIT_COUNT = 5;    private final int MAX_COUNT = 30;    private int count = 0;        private final Object wait = new Object();        private  LinkedList<Connection> CONN_POOL;    private DatabaseConnection() {        CONN_POOL = new LinkedList<Connection>();        try {            Class.forName("com.mysql.jdbc.Driver");            for (int i = 0; i < INIT_COUNT; i++) {                Connection connection = createConnection();                if(connection != null) {                    CONN_POOL.add(createConnection());                    count++;                }            }     //       Connection connection = getConnection();     //       Statement stmt = connection.createStatement();     //       stmt.execute(CREATE_TABLE_TWITTER);     //       stmt.execute("set names 'utf-8'");     //       stmt.close();     //       releaseConnection(connection);        } catch (Exception e) {            e.printStackTrace();        }    }        public static DatabaseConnection getInstance() {        return instance;    }        private static Connection createConnection() {        try {            return DriverManager.getConnection(url, USERNAME, PASSWORD);        } catch (SQLException e) {            e.printStackTrace();        }        return null;    }    public Connection getConnection() {        synchronized (CONN_POOL) {            while(CONN_POOL.size() > 0) {                Connection conn = CONN_POOL.removeLast();                try {                    if(conn.isValid(1000)) {                        return conn;                    } else {                        count--;                    }                } catch (SQLException e) {                    e.printStackTrace();                }            }            if(count < MAX_COUNT) {                count++;                return createConnection();            }             synchronized (wait) {                try {                    wait.wait(3000);                    if(CONN_POOL.size() > 0) {                        return CONN_POOL.removeLast();                    }                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }        return null;    }    public void releaseConnection(Connection connection) {        CONN_POOL.add(connection);        synchronized (wait) {            wait.notify();        }    }    }
其中count用于保存当前连接数(包括闲置和在使用的)。

wait对象用于线程同步锁,主要是获取不到连接并且需要等其他连接被还回来时使用,在getConnection()里面调用 wait,而在releaseConnection()方法中,也就是释放连接时,调用 notify通知其他等待的线程。

另外,在公用的数据库当中,数据库连接通常是不作长连接的。所以在这里连接池中的连接,可能是已经断开的或者是无效的,所以在获取连接时需要判断一下当前拿到的连接是否还有效。没有的话就拿下一个。

1 1