JAVA自定义连接池原理设计(一)

一,概述

本人认为在开发过程中,需要挑战更高的阶段和更优的代码,虽然在真正开发工作中,代码质量和按时交付项目功能相比总是无足轻重。但是个人认为开发是一条任重而道远的路。现在本人在网上找到一个自定义连接池的代码,分享给大家。无论是线程池还是db连接池,他们都有一个共同的特征:资源复用,在普通的场景中,我们使用一个连接,它的生命周期可能是这样的:

一个连接,从创建完毕到销毁,期间只被使用一次,当周期结束之后,另外的调用者仍然需要这个连接去做事,就要重复去经历这种生命周期。因为创建和销毁都是需要对应服务消耗时间以及系统资源去处理的,这样不仅浪费了大量的系统资源,而且导致业务响应过程中都要花费部分时间去重复的创建和销毁,得不偿失,而连接池便被赋予了解决这种问题的使命!

二,连接池简要需求

和原始周期相比,连接池多了一下特性:

1,创建并不是真的创建,而是从池子中选出空闲连接。

2,销毁并不是真的销毁,而是将使用中的连接放回池中。

3,真正的创建和销毁由线程池的特性机制来决定。

4,保存连接的容器是必不可少的,另外,该容器也要支持连接的添加和移除功能,并保证线程安全。

5,我们需要因为要对连接的销毁做逻辑调整,我们需要重写它的close以及isClosed方法。

6,我们需要有个入口对连接池做管理,例如回收空闲连接,连接池不仅仅只是对Connection生命周期的控制,还应该加入一些特色,例如初始连接数,最大连接数,最小连接数、最大空闲时长以及获取连接的等待时长,这些我们也简单支持一下。

容器连接池的选型:

1,要保证线程安全,我们可以将目标瞄准在JUC包下的神通们,设我们想要的容器为X,那么X不仅需要满足基本的增删改查功能,而且也要提供获取超时功能,这是为了保证当池内长时间没有空闲连接时不会导致业务阻塞,即刻熔断。另外,x需要满足双向操作,这是为了连接池可以识别出饱和的空闲连接,方便回收操作。

综上所述,LinkedBlockingDeque是最合适的选择,它使用InterruptibleReentrantLock来保证线程安全,使用Condition来做获取元素的阻塞,另外支持双向操作。

另外,我们可以将连接池分为3个类型:

工作池:存在正在被使用的连接。

空闲池:存在空闲连接。

回收池:已经被回收(物理关闭)的连接。

其中,工作池和回收池大可不必用双向队列,或许用单向队列或者set都可以代替之:

private LinkedBlockingQueue<HoneycombConnection> workQueue;
private LinkedBlockingQueue<HoneycombConnection> idleQueue;
private LinkedBlockingQueue<HoneycombConnection> freezeQueue;

Connection 的装饰

连接池的输出是Connection,它代表着一个db连接,上游服务使用它做完操作后,会直接调用它的close方法来释放连接,而我们必须做的是在调用者无感知的情况下改变它的关闭逻辑,当调用close的方法时,我们将它放回空闲队列中,保证其的可复用性!

因此,我们需要对原来的Connection做装饰,其做法很简单,但是很累,这里新建一个类来实现Connection接口,通过重写所有的方法来实现一个“可编辑”的Connection,我们称之为Connection的装饰者:

public class HoneycombConnectionDecorator implements Connection{

    protected Connection connection;

    protected HoneycombConnectionDecorator(Connection connection) {
        this.connection = connection;
    }

    此处省略对方法实现的三百行代码...
}

之后,我们需要新建一个自己的Connection来继承这个装饰者,并重写相应的方法:

public class HoneycombConnection extends HoneycombConnectionDecorator implements HoneycombConnectionSwitcher{
    @Override
    public void close() { do some things }

    @Override
    public boolean isClosed() throws SQLException { do some things }    

    省略...
}

DataSource的重写

DataSource是JDK为了更好的统合和管理数据源而定义出的一个规范,获取连接的入口,方便我们在这一层更好的扩展数据源(例如增加特殊属性),使我们的连接池的功能更加丰富,我们需要实现一个自己的DataSource

public class HoneycombWrapperDatasource implements DataSource{
    protected HoneycombDatasourceConfig config;
    省略其它方法的实现...
    @Override
    public Connection getConnection() throws SQLException {
        return DriverManager.getConnection(config.getUrl(), config.getUser(), config.getPassword());
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return DriverManager.getConnection(config.getUrl(), username, password);
    }
    省略其它方法的实现...
}

我们完成了对数据源的实现,但是这里获取连接的方式是物理创建,我们需要满足池化的目的,需要重写HoneycombWrapperDatasource中的连接获取逻辑,做法是创建一个新的类对父类方法重写:

public class HoneycombDataSource extends HoneycombWrapperDatasource{
    private HoneycombConnectionPool pool;
    @Override
    public Connection getConnection() throws SQLException {
        这里实现从pool中取出连接的逻辑
    }
    省略...
}

特性扩展

在当前结构体系下,我们的连接池逐渐浮现出了雏形,但远远不够的是,我们需要在此结构下可以做自由的扩展,使连接池对连接的控制更加灵活,因此我们可以引入特性这个概念,它允许我们在其内部访问连接池,并对连接池做一系列的扩展操作:

public abstract class AbstractFeature{
    public abstract void doing(HoneycombConnectionPool pool);
}

AbstractFeature抽象父类需要实现doing方法,我们可以在方法内部实现对连接池的控制,其中一个典型的例子就是对池中空闲连接左回收:

public class CleanerFeature extends AbstractFeature{
    @Override
    public void doing(HoneycombConnectionPool pool) {
        这里做空闲连接的回收
    }
}

三,落实计划

原文地址:https://www.cnblogs.com/boanxin/p/10962053.html

时间: 2024-10-07 06:33:09

JAVA自定义连接池原理设计(一)的相关文章

java自定义连接池

1.java自定义连接池 1.1连接池的概念: 实际开发中"获取连接"或"释放资源"是非常消耗系统资源的两个过程,为了姐姐此类性能问题,通常情况我们采用连接池技术来贡献连接Connection 用池来管理Connection,这样可以重复使用Connection,有了池,所以我们就不用自己来创建Connection,而是通过池来获取Connection对象,当使用完Connection后,调用Connection的close()方法也不会真的关闭Connection

自定义连接池(装饰者模式)

连接池概述: 管理数据库的连接, 作用: 提高项目的性能. 就是在连接池初始化的时候存入一定数量的连接,用的时候通过方法获取,不用的时候归还连接即可. 所有的连接池必须实现一个接口 javax.sql.DataSource接口 获取连接方法: Connection getConnection() 归还连接的方法就是以前的释放资源的方法.调用connection.close(); 增强方法: 1.继承 2.装饰者模式(静态代理) 3.动态代理 装饰者模式: 使用步骤: 1.装饰者和被装饰者实现同一

线程池;java实现线程池原理

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中.如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙.如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值.超过最大值的线程可以排队,但他们要等到其他线程完成后才启动. 组成部分 1.线程池

JDBC自定义连接池

最近学习了JDBC的相关知识,写一下自定义连接池 一些说明: 本代码参考了部分别人的代码!!! JDBCCon类具体创建了连接: MyConnection类集成了Connection类用来管理连接与池,其中的close方法必须pool.add(): MyDataSource则是具体实现连接池. 具体步骤: 1.导mysql的jar包 2.配置db.propertites 1 driver = com.mysql.cj.jdbc.Driver 2 url = jdbc:mysql://localh

Java 自定义线程池

Java 自定义线程池 https://www.cnblogs.com/yaoxiaowen/p/6576898.html public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandle

《java数据源—连接池》

<java数据源-连接池>1.数据源的分类:直接数据源.连接池数据源.2.连接池.数据源.JNDI a.数据源:Java中的数据源就是连接到数据库的一条路径,数据源中并无真正的数据,它仅仅记录的是你连接到哪个数据库,以及如何连接. b.连接池:简单的说就是保存所有的数据库连接的地方,在系统初始化时,将数据库连接对象存储到内存里,当用户需要访问数据库的时候,并不是建立一个新的连接,而是从连接池中 取出一个已经建立好的空闲连接对象.而连接池负责分配.管理.释放数据库连接对象.注意的是:连接池是由容

自定义连接池的问题及解决分析

1.1.1 自定义连接池的问题:1.1.1.1 使用接口的实现类完成的构造MyDataSource dataSource = new MyDataSource();这种写法不方便程序的扩展.1.1.1.2 额外提供了方法归还连接 // 归还连接: dataSource.addBack(conn); 这种方式增加使用连接池的用户的难度.1.1.2 自定义连接池的问题解决如果不提供自定义的方法就可以解决这个问题,但是连接要如何归还到连接池呢?1.1.2.1 解决分析的思路原来在Connection中

数据库连接池原理详解与自定义连接池实现

实现原理 数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数制约.无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量.连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中. 连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象.使

Java——DBCP连接池

p { margin-bottom: 0.25cm; direction: ltr; color: #000000; line-height: 120%; text-align: justify; widows: 0; orphans: 0 } p.western { font-family: "Calibri", sans-serif; font-size: 10pt } p.cjk { font-family: "宋体", "SimSun";