小艾的学习笔记Day0 --->手写连接池简单实现

本文介绍了作者手写实现JDBC连接池的过程,使用装饰者模式优化,包括创建DataSource接口、抽象类MyAbstractDataSource和具体实现MyDataSource,以及MyConnection类的装饰。通过测试展示了连接池的使用和超时特性。
摘要由CSDN通过智能技术生成

小艾的学习笔记Day0—>手写连接池简单实现

前言:又又又是我们老师,因为最近在学习JDBC要求我们手写连接池,

之前学过线程池知道池化主要是缓存,资源重复利用减少开销,经过一阵百度

看了别了写的又是装饰者模式又是动态代理的,没学过不会呀,经过一阵研究

装饰者模式还是比较容易理解的下面我写的连接池就有用到。

主要思路

主要思路其实很简单

1、DataSource定义连接属性url用户名密码啥的。

2、需要定义两个List,一个用来放空闲连接一个用来放工作连接。

3、使用装饰者模式代理Connecion对象,重写关闭方法。

上代码

MyDataSource

1、自定义MyDataSourceInterface继承Java的DataSource接口,默认实现他的方法因为我们只需要重写getConnection方法就好了。

2、MyAbstractDataSource实现MyDataSourceInterFace接口重写getConnection方法,从MySQL获得的连接。

3、MyDataSource继承MyAbstractDataSource重写getConnection方法,从线程池获得连接的方法。

MyDataSourceInterface接口
在这里插入图片描述

MyAbstractDataSource抽象类

在这里插入图片描述

MyAbstractDataSource得到连接的方法

   // 重写得到连接方法
    @Override
    public Connection getConnection() throws SQLException {
        return getConnection(username,password);
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return doGetConnection(username,password);
    }

    private Connection doGetConnection(String username, String password) throws SQLException {
        if (!initFlag) {
            try {
                Class.forName(driverClassName);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            initFlag = true;
        }
        return DriverManager.getConnection(url, username,password);
    }

MyDataSource类

MyDataSource得到连接的方法从空闲池

  @Override
    public Connection getConnection() throws SQLException, RuntimeException {
        MyConnection connection = null;
        this.init();
        while (connection == null) {
            // 线程同步上锁
            synchronized (lock) {
                // 如果空闲连接池不为空,那么就可以直接获取
                if (!idlePool.isEmpty()) {
                    connection = idlePool.removeFirst();
                } else {
                    // 如果工作连接数小于最大连接数就创建一个
                    if (workPool.size() < super.getMaxActive()) {
                        connection = new MyConnection(this,
                                super.getConnection());
                    }
                    // 否则不能创建连接的需要等待 maxWait 3000毫秒
                }

                if (connection == null) {
                    try {
                        long statr = System.currentTimeMillis();
                        lock.wait(super.getMaxWait());
                        long end = System.currentTimeMillis();
                        if ((end - statr) >= super.getMaxWait()) {
                            throw new RuntimeException("连接超时" + (end - statr));
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        // 如果线程被打断退出循环
                        break;
                    } catch (Exception e) {
                        e.printStackTrace();
                        // 连接超时退出循环
                        break;
                    }
                }
            }
        }

        // 连接不为空添加到工作连接
        if (connection != null) {
            workPool.addLast(connection);
        }
        return connection;
    }

    public void init() {
        if (!initFlag) {
            initLock.lock();
            try {
                // 初始化空闲连接池
                while (idlePool.size() < super.getInitialSize()) {
                    try {
                        MyConnection connection = new MyConnection(this, super.getConnection());
                        idlePool.addLast(connection);
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                initLock.unlock();
            }
            initFlag = true;
        }
    }

MyConnection

1、实现java的Connection接口,构造方法转入MyDataSource和要装饰的Connection对象

这里传入的connection对象是MySQL实现的connection对象,真正应用的还是MySQL的

Connection对象的方法,我们只是重写了关闭连接的方法

2、重写close方法,放回空闲连接池,this指向调用者谁调用closethis就指向谁

3、关于装饰者模式我百度了一下

装饰者模式也称为包装模式(Wrapper Pattern),属于结构型设计模式。

该模式对客户端透明的方式来动态的扩展对象,(对扩展开放,对修改关闭)

同时该模式也是继承关系的一种替代方法之一。

总之就是动态的给对象添加一些额外的职责,类似钢铁侠可以组装不同武器。

在这里插入图片描述

在这里插入图片描述

测试

连接测试

对比传统连接

@Test
public void testMyDataSource() throws SQLException {
    String url = "jdbc:mysql://localhost:3306/java001?useServerPrepStmts=true";
    String username = "root";
    String password = "root";
    String driverClassName = "com.mysql.cj.jdbc.Driver";
    myDataSource.setUrl(url);
    myDataSource.setUsername(username);
    myDataSource.setPassword(password);
    myDataSource.setDriverClassName(driverClassName);
    Connection connection = myDataSource.getConnection();
    System.out.println("使用连接池后空闲连接池的数量" + myDataSource.getIdlePool().size());
    System.out.println(connection);
    connection.close();
    System.out.println("关闭连接后空闲连接池的数量" + myDataSource.getIdlePool().size());
    System.out.println(myDataSource);

    long start = System.nanoTime();
    for (int i = 0; i < 500; i++) {
        Connection connection1 = myDataSource.getConnection();
        connection1.close();

    }
    long end = System.nanoTime();
    System.out.println("MyDataSource:" + (end - start));
    
    start = System.nanoTime();
    for (int i = 0; i < 500; i++) {
        Connection connection1 = DriverManager.getConnection(url, username, password);
        connection1.close();
    }
    end = System.nanoTime();
    System.out.println("DriverManager:" + (end - start));
}

输出结果:

在这里插入图片描述
在这里插入图片描述

超时测试

最大连接是30

最大等待时间3000毫秒

druid连接池

@Test
public void testDruidMaxWait() throws SQLException, InterruptedException {
    List<Connection> list = new ArrayList<>();
    for (int i = 0; i < 31; i++) {
        Connection connection = JDBCUtil.getConnection();
        list.add(connection);
    }
    System.out.println(list.size());
}

输出结果:
在这里插入图片描述

MyDatasource

    @Test
    public void testMaxWait() throws SQLException, InterruptedException {
        myDataSource.setUrl(url);
        myDataSource.setUsername(username);
        myDataSource.setPassword(password);
        myDataSource.setDriverClassName(driverClassName);
        LinkedList<Connection> list = new LinkedList<>();
        for (int i = 0; i < 31; i++) {
            Connection connection = myDataSource.getConnection();
            list.add(connection);
        }
        System.out.println(list.size());
    }

输出结果:

在这里插入图片描述

end

  • 8
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值