数据库连接池的简单实现

来源:互联网 发布:java调用 webservice 编辑:程序博客网 时间:2024/05/16 13:57

应用springMVC+hibernate做了许久的开发,发现基础却忘得差不多了。 刚好空闲时间,简单实现一个数据库连接池。

数据库连接是一种关键的、有限的、昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。所以数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数制约。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。
所以要完成以上的目标,主要的就是设计一个池来存放初始化好的数据库连接线程,可以用来存与取线程,当jdbc处理完之后,闭关连接并不是关闭线程,而是将线程重新放入池中。这里,因为考虑到多线程和删除与插入处理,所以使用LinkedBlockingQueue类来当连接池的容器。
LinkedBlockingQueue类参考http://blog.csdn.net/tayanxunhua/article/details/20962307

/** *  * @ClassName JdbcPool  * @Description 编写数据库连接池 * @author city_black * @time 2016年12月24日 下午4:10:02 * */public class JdbcPool implements DataSource{/*** @Field: listConnections*         使用BlockingQueue类当连接池容器*/ private static BlockingQueue<Connection> listConnections = new LinkedBlockingQueue<>();static{    //在静态代码块中加载db.properties数据库配置文件    InputStream in = JdbcPool.class.getResourceAsStream("/db.properties");    Properties prop = new Properties();    try {        prop.load(in);        String driver = prop.getProperty("driver");        String url = prop.getProperty("url");        String username = prop.getProperty("user");        String password = prop.getProperty("password");        //数据库连接池的初始化连接数大小        int jdbcPoolInitSize =Integer.parseInt(prop.getProperty("poolInitSize"));        //加载数据库驱动        Class.forName(driver);        for (int i = 0; i < jdbcPoolInitSize; i++) {            Connection conn = DriverManager.getConnection(url, username, password);            //将获取到的数据库连接加入到listConnections集合中,listConnections集合此时就是一个存放了数据库连接的连接池            listConnections.add(conn);        }    } catch (Exception e) {        throw new ExceptionInInitializerError(e);    }}@Overridepublic PrintWriter getLogWriter() throws SQLException {    // TODO Auto-generated method stub    return null;}@Overridepublic void setLogWriter(PrintWriter out) throws SQLException {    // TODO Auto-generated method stub}@Overridepublic void setLoginTimeout(int seconds) throws SQLException {    // TODO Auto-generated method stub}@Overridepublic int getLoginTimeout() throws SQLException {    // TODO Auto-generated method stub    return 0;}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {    // TODO Auto-generated method stub    return null;}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {    // TODO Auto-generated method stub    return false;}/* 获取数据库连接 *  */@Overridepublic Connection getConnection() throws SQLException {   try {               //获取listConnections的队头,当listConnections.size()=0时,take()将阻塞直到有新线程重新回到容器                final Connection conn = listConnections.take();                return (Connection) Proxy.newProxyInstance(JdbcPool.class.getClassLoader(), new Class[] { Connection.class }, new InvocationHandler(){                    @Override                    public Object invoke(Object proxy, Method method, Object[] args)                            throws Throwable {                        if(!method.getName().equals("close")){                            System.out.println("获取conn:"+conn);                            return method.invoke(conn, args);                        }else{                            //如果调用的是Connection对象的close方法,就把conn还给数据库连接池                            listConnections.add(conn);                            System.out.println(conn + "被还给数据库连接池了!!");                            System.out.println("数据库连接池大小为" + listConnections.size());                            return null;                        }                    }                });            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }}@Overridepublic Connection getConnection(String username, String password)        throws SQLException {    return null;}@Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {    // TODO Auto-generated method stub    return null;}}

编写一个jdbcUtil

/** *  * @ClassName  JDBCUtil  * @Description 数据库连接工具 * @author city_black * @time 2016年12月24日下午5:03:17 * */public class JDBCUtil {    /**     *      */    private static DataSource jdbcPool = new JdbcPool();    /**     *      * @Method: getConnection        * @Description: 从数据库连接池获取对象      *     */    public static Connection getConnection(){        try{            return jdbcPool.getConnection();        }catch(SQLException sq){            sq.printStackTrace();        }        return null;    }    /***     *      * @Method: close        * @Description: 资源释放     * @param conn -数据库连接      *     */    public static void close(Connection conn,Statement stat, ResultSet rs){        if(conn!=null){            try {                conn.close();            } catch (SQLException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }        if(stat!=null){            try {                stat.close();            } catch (SQLException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }        if(rs!=null){            try {                rs.close();            } catch (SQLException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    }}

配置文件 db.properties

driver=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/tryuser=rootpassword=123456poolInitSize=40

多线程访问的测试类

public class Start {    public static void main(String[] args) throws InterruptedException{        List<Thread> ts = new ArrayList<>();        for(int i=0;i<1000;i++){            String sql = "INSERT INTO user (username,password) values ('lzh',"+i+""+")";            Thread t = new Thread(new ThreadC(sql));            ts.add(t);        }        long time = new Date().getTime();        for(Thread t : ts){            t.start();        }        for(Thread t : ts){            t.join();        }           System.out.println("需要的时间:"+(new Date().getTime()-time));    }}    class ThreadC implements Runnable{        private String sql;        public ThreadC(){    }    public ThreadC(String sql) {        // TODO Auto-generated constructor stub        this.sql =sql;    }    @Override    public void run() {        // TODO Auto-generated method stub        Connection conn=null;        ResultSet rs = null;        Statement stat = null;        try {            conn = JDBCUtil.getConnection();            stat = conn.createStatement();            stat.execute(sql);              } catch (SQLException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }finally {            JDBCUtil.close(conn, stat, rs);        }    }}
0 0
原创粉丝点击