ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

连接池的一次实验

2021-07-17 21:05:18  阅读:113  来源: 互联网

标签:一次 rs System num 实验 mysql 连接 连接池


一、前言

  话说在Java开发中,连接总是是必不可少的。有数据库连接、http连接等。面试内容也会经常问起(虽然我没被面到过:)。那究竟什么是连接池呢?它有什么作用?又是怎么实现的呢?

二、什么和为什么?

  常见连接的代码通常要经历建立连接、处理业务和关闭连接三个步骤。伪代码如下:

Connection cnn =null;
try{
    cnn = getConnection();
    cnn.excute();
}finally{
    cnn.close();
}

这种情况在少数并发情况下,简单实用。可一旦面临多并发情况下就显得有些不够用了。这里的瓶颈在于每次都需要创建连接和关闭连接,这种其实重复且耗时。比如mysql其实是会缓存常用的连接,达到性能优化的效果,如果应用端频繁关闭和新建连接,那其实就用不到这种优化了。如果能复用连接,预先创建连接池,使用时拿取一个,用完再归还,从而减少创建和关闭的消耗,那必然是能达到优化的效果了。而这就是为什么采用连接池的原因了。

  那至于什么是连接池?那根据上面的描述不难得出,连接池必然有以下元素:1、连接集合 2、获取连接 3、释放(归还)连接。只要具备这三样基本就能称之为连接池了。不会动手的程序猿,不是一个好攻城狮。接下来就动手试试?

三、实验

  本次实验就以Java的mysql连接为例,测试普通连接方式和连接池方式的性能吧。

  JdbcCnnPool类:

public class JdbcCnnPool {

    private static final Integer poolSize = 20;

    private static final ReentrantLock getLock = new ReentrantLock();

    private static final ReentrantLock releaseLock = new ReentrantLock();

    private static final List<Connection> cnnList = new ArrayList<>();


    static public Connection getConnection() throws Exception {
        try {
            getLock.lock();
            if (CollectionUtils.isEmpty(cnnList)) {
                for (int i = 0; i < poolSize; i++) {
                    String URL = "jdbc:mysql://127.0.0.1:3306/db1?useUnicode=true&characterEncoding=utf-8";
                    String USER = "root";
                    String PASSWORD = "root1234";
                    //1.加载驱动程序
                    Class.forName("com.mysql.jdbc.Driver");
                    //2.获得数据库链接
                    Connection cnn = DriverManager.getConnection(URL, USER, PASSWORD);
                    cnnList.add(cnn);
                }
            }
            return cnnList.remove(0);
        } catch (Exception e) {
            throw e;
        } finally {
            getLock.unlock();
        }
    }

    static public void releaseConnection(Connection connection) {
        try {
            releaseLock.lock();
            if (cnnList.size() <= poolSize) {
                cnnList.add(connection);
            }
        } catch (Exception e) {

        } finally {
            releaseLock.unlock();
        }
    }

}

测试类:

public class ConnectionTest {

    @Test
    public void connectionTest() throws Exception {

        int num = 100;
        newConnectionTest(num);
        connectionPoolTest(num);
    }


    private void newConnectionTest(int num) throws Exception {
        Long startTime = System.currentTimeMillis();
        for (int i = 0; i < num; i++) {
            String URL = "jdbc:mysql://127.0.0.1:3306/db1?useUnicode=true&characterEncoding=utf-8";
            String USER = "root";
            String PASSWORD = "root1234";
            //1.加载驱动程序
            Class.forName("com.mysql.jdbc.Driver");
            //2.获得数据库链接
            Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
            Statement st = conn.createStatement();
            ResultSet rs = st.executeQuery("select * from user");
            //4.处理数据库的返回结果(使用ResultSet类)
            while (rs.next()) {
//                System.out.println(rs.getString("name") + " "
//                        + rs.getString("pwd"));
            }
            //关闭资源
            rs.close();
            st.close();
            conn.close();
        }
        Long endTime = System.currentTimeMillis();
        System.out.println("newConnectionTest " + (endTime - startTime));

    }

    private void connectionPoolTest(int num) throws Exception {
        Long startTime = System.currentTimeMillis();
        for (int i = 0; i < num; i++) {
            Connection conn = JdbcCnnPool.getConnection();
            try {
                Statement st = conn.createStatement();
                ResultSet rs = st.executeQuery("select * from user");
                while (rs.next()) {
//                    System.out.println(rs.getString("name") + " "
//                            + rs.getString("pwd"));
                }

            } catch (Exception e) {

            } finally {
                JdbcCnnPool.releaseConnection(conn);
            }

        }
        Long endTime = System.currentTimeMillis();
        System.out.println("connectionPoolTest " + (endTime - startTime));

    }

}

实验结果:

1、100次查询(连接数据库)

正常连接执行时间:2553

连接池执行时间:322

2、1000次查询

正常连接执行时间:8376

连接池执行时间:356

3、10000次查询

正常连接执行时间:64627

连接池执行时间:1407

基本可以看出,连接池的方式的性能是正常的10倍以上,所以连接池还是很有用的。当然基本现在的连接工具基本都是采用连接池的,比如druid、c3p0、tomcat-jdbc,理解连接池的基本原理也能更好的帮助理解源码了。

四、总结

   连接池是个好东西,生产上能用则用。多看轮子,多造小轮子,为了造更好的轮子!

标签:一次,rs,System,num,实验,mysql,连接,连接池
来源: https://www.cnblogs.com/ariczky/p/15024750.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有