连接池

一、为什么会产生连接池?

我们现在考虑:

程序中连接为什么要来管理?因为连接资源宝贵,所以我们要来对连接资源进行管理

如何高效的来进行管理?频繁的连接,打开、关闭,这会严重影响程序的运行效率!所以我们引入连接池的概念。

二、何为连接池?

普通的连接:

  1. 操作数据库,创建连接。
  2. 操作结束,关闭!

使用连接池管理:

  1. 预先创建一组连接,有的时候每次取出一个。
  2. 用完后,放回。

连接池就好比图书馆,我们想要看书去借阅,看完之后我们要归还。就是借与还的关系。

三、学习连接池

3.1、自定义连接池

/*
     *  * 自定义连接池, 管理连接
     * 代码实现:
    1.  MyPool.java  连接池类,
    2.  指定全局参数:  初始化数目、最大连接数、当前连接、   连接池集合
    3.  构造函数:循环创建3个连接
    4.  写一个创建连接的方法
    5.  获取连接
    ------>  判断: 池中有连接, 直接拿
     ------>                池中没有连接,

    ------>                 判断,是否达到最大连接数; 达到,抛出异常;没有达到最大连接数,

    创建新的连接
    6. 释放连接
     ------->  连接放回集合中(..)
     */
    private int init_count=3;  //初始化连接数目
    private int max_count=6;   //最大连接数目
    private int current_count=0; //记录当前使用连接数目
    //连接池,存放所有的初始化连接
    private LinkedList<Connection> pool=new LinkedList<Connection>();

    //1.构造函数,初始化连接放入连接池
    public MyPool(){
        for(int i=0;i<init_count;i++){
            //记录当前的数目
            current_count++;
            //创建原始的连接对象,加入连接池
            pool.addLast(createConnection());
        }
    }

    //2. 创建一个新的连接的方法
    //使用代理模式,来监测 close方法,当关闭时候,自动加入连接池
    private Connection createConnection(){

        try {
            Class.forName("com.mysql.jdbc.Driver");
            final Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc_demo", "root", "root");
            Connection proxy=(Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), new Class[]{Connection.class},
                    new InvocationHandler() {

                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args)
                                throws Throwable {
                            // TODO Auto-generated method stub
                            Object result=null;
                            String name=method.getName();
                            if("close".equals(name)){
                                if(pool.size()<init_count){
                                System.out.println("begin:当前执行close方法开始!");
                                // 连接放入连接池 (判断..)
                                pool.addLast(conn);
                                System.out.println("end: 当前连接已经放入连接池了!");
                                }else{
                                    current_count--;
                                    conn.close();
                                }
                            }else{
                                method.invoke(conn, args);
                            }
                            return result;
                        }

                    }
                    );
            return proxy;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    //获得连接
    public Connection getConnection(){
        if(pool.size()>0){ //连接池有,直接获取
            return pool.removeFirst();
        }
        if(current_count<max_count){ //连接池没有,小于最大连接,自己创建连接
            current_count++;
            return createConnection();
        }
        throw  new RuntimeException();//没有连接使用,抛出异常

    }

    //释放连接
    public void realeaseConnection(Connection conn){
        if(pool.size()<init_count){
            pool.addLast(conn);
        }else{
            current_count--;
            try {
                conn.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    

为什么使用LinkedList集合?

因为LinkedList集合含有.removeFirst()方法,这样我们可以删除第一个元素,并且返回第一个元素

3.2开源的连接池技术

概述:

Sun公司约定: 如果是连接池技术,需要实现一个接口! javax.sql.DataSource;

3.2.1、DBCP连接池

核心类:BasicDataSource

// 1. 硬编码方式实现连接池
        @Test
        public void testDbcp() throws Exception {
            BasicDataSource bds=new BasicDataSource(); //创建核心类
            bds.setDriverClassName("com.mysql.jdbc.Driver"); //数据库驱动
            bds.setUrl("jdbc:mysql://localhost:3306/jdbc_demo"); //数据库连接字符
            bds.setUsername("root"); //数据库用户名
            bds.setPassword("root");//数据库密码
            bds.setInitialSize(3); //初始化连接
            bds.setMaxActive(6);//最大连接数目
            bds.setMaxIdle(3000);//最大休闲时间
            String sql="select * from admin where id=5";
            //获取连接
            Connection conn=bds.getConnection();
            PreparedStatement pstmt=conn.prepareStatement(sql);
            System.out.println(pstmt.execute());
            conn.close();
        }

        // 2. 【推荐】配置方式实现连接池  ,  便于维护
        @Test
        public void testDBCP() throws Exception {
             // 获取文件流
            InputStream inputStream=App_DBCP.class.getResourceAsStream("/db.properties");
            // 加载prop配置文件
            Properties prop=new Properties();
            prop.load(inputStream);

            // 根据prop配置,直接创建数据源对象
            DataSource ds=BasicDataSourceFactory.createDataSource(prop);
            String sql="select * from admin where id=5";
            //获取连接
            Connection conn=ds.getConnection();
            PreparedStatement pstmt=conn.prepareStatement(sql);
            System.out.println(pstmt.execute());
            conn.close();
        }

配置文件为db.properties,配置文件中的key与BaseDataSouce中的属性一样:

url=jdbc:mysql://localhost:3306/jdbc_demo
driverClassName=com.mysql.jdbc.Driver
username=root
password=root
initialSize=3
maxActive=6
maxIdle=3000

3.2.1、DBCP连接池

C3P0连接池:

最常用的连接池技术!Spring框架,默认支持C3P0连接池技术!

C3P0连接池,核心类:

CombopooledDataSource ds;

package cn.lyjs.c3p0;

import static org.junit.Assert.*;

import java.sql.Connection;

import org.junit.Test;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class C3P0 {

    //1. 硬编码方式,使用C3P0连接池管理连接
    @Test
    public void testCode() throws Exception {
        // 创建连接池核心工具类
        ComboPooledDataSource dataSource=new ComboPooledDataSource();
        // 设置连接参数:url、驱动、用户密码、初始连接数、最大连接数
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc_demo");
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setUser("root");
        dataSource.setPassword("root");
        dataSource.setInitialPoolSize(3);
        dataSource.setMaxPoolSize(6);
        dataSource.setMaxIdleTime(3000);
        String sql="delete from admin where id=6";
        Connection conn=dataSource.getConnection();
        conn.prepareStatement(sql).executeUpdate();
        conn.close();
    }

    //2. XML配置方式,使用C3P0连接池管理连接
    @Test
    public void testXml() throws Exception {
                // 创建c3p0连接池核心工具类
                // 自动加载src下c3p0的配置文件【c3p0-config.xml】
        ComboPooledDataSource dataSource=new ComboPooledDataSource();
        String sql="delete from admin where id=7";
        Connection conn=dataSource.getConnection();
        conn.prepareStatement(sql).executeUpdate();
        conn.close();
    }
}
c3p0-config.xml,配置文件
<c3p0-config>
    <default-config>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc_demo</property>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="user">root</property>
        <property name="password">root</property>
        <property name="initialPoolSize">3</property>
        <property name="maxPoolSize">6</property>
        <property name="maxIdleTime">1000</property>
    </default-config>

    <named-config name="oracle_config">
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc_demo</property>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="user">root</property>
        <property name="password">root</property>
        <property name="initialPoolSize">3</property>
        <property name="maxPoolSize">6</property>
        <property name="maxIdleTime">1000</property>
    </named-config>

</c3p0-config>
时间: 2024-10-05 11:11:16

连接池的相关文章

oracle database resident connection pooling(驻留连接池)

oracle在11g中引入了database resident connection pooling(DRCP).在此之前,我们可以使用dedicated 或者share 方式来链接数据库,dedicated方式是oracle数据库默认的链接方式,无需过多的配置,而且关于dedicated的bug也是非常少的,因此,通常情况下,建议使用dedicated方式来链接数据库.但是,在服务器资源有限,并且同时连接数据库的用户量非常大时,dedicated方式就无能为力了.假设并发用户为5000,每个d

缓冲池,线程池,连接池

SSH:[email protected]:unbelievableme/object-pool.git   HTTPS:https://github.com/unbelievableme/object-pool.git 缓冲池 设计要点:包含三个队列:空缓冲队列(emq),装满输入数据的输入的队列(inq),装满输出数据的输出队列(outq),输入程序包括收容输入(hin),提取输入(sin),输出程序包括收容输出(hout)和提取输出(sout). 注意点:输入程序和输出程序会对缓冲区并发访

DBCP连接池使用问题

问题现象: 启动应用,访问无压力,一切正常,一段时间过后,应用访问异常. 问题分析: 1.web容器线程爆满,拒绝服务.由于应用并发量大,线程响应时间长增加,线程池连接数逐步递增直到爆满,导致应用拒绝服务. 2.通过对线程信息的分析,发现线程处理时间都卡在连接数据库中,通过对数据库服务器的检查,数据库是没有问题的. 3.通过查询服务器日志,发现数据库连接异常:连接超时. 4.查询DBCP连接池连接使用情况,空闲链接和使用链接还正常. 问题思考: 从以上信息可以确认,问题一定出在应用层,并且是应用

一种利用ADO连接池操作MySQL的解决方案(VC++)

VC++连接MySQL数据库 常用的方式有三种:ADO.mysql++,mysql API ; 本文只讲述ADO的连接方式. 为什么要使用连接池? 对于简单的数据库应用,完全可以先创建一个常连接(此连接永远不关闭,直接数进程退出),但是这样做至少会引起两个问题:(1)资源竞争,多个数据库请求操作不能同时进行,后一请求必须要等到前一请求完成后才能进行:(2)多线程情况下容易出现混乱,甚至出现资源异常释放.还有一种方法,就是使用数据库时创建连接,使用完后关闭连接回收资源.这种方式在数据库操作频繁的情

mongodb or操作与连接池

mongodb # 类似于sql中的in或者or操作 mulites field query: db.cool.find({$or:[{field1:'val'},{'field2':'val'}-]}) # 类似于sql中的like操作 db.coo.find('name': /m/) == sql like pymongo 使用 {'field':{$regex: keyword}} http://stackoverflow.com/questions/3305561/how-do-i-qu

JBoss配置连接池

什么是数据库连接池? 配置连接池为的是解决效率问题.因为每创建一个连接都是很耗时的,有了连接池,就可以提前放一些连接进去.以后我们再用连接就去连接池里面取而不是每次都创建.但是我们知道连接池是有上限的,如果只允许我们放10个,那么当这10个连接都被占用的时候,下一个用户再来请求连接将不能得到,只好等待,如果等的时间太长了就会抛出timeout的异常.使用完连接后要释放,否则会一直占着资源,当连接全部被占用而得不到释放时,就会出现错误... JBoss实现了J2EE的13个规范包括JNDI,JND

DBCP连接池与c3p0连接池

1.   DBCP连接池 2.  c3p0连接池(参见上一篇的使用步骤http://www.cnblogs.com/qlqwjy/p/7545012.html)

redis 连接池 - 转载

所需jar:jedis-2.1.0.jar和commons-pool-1.5.4.jar Jedis操作步骤如下:1->获取Jedis实例需要从JedisPool中获取:2->用完Jedis实例需要返还给JedisPool:3->如果Jedis在使用过程中出错,则也需要还给JedisPool: package com.ljq.utils; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; imp

redis mysql 连接池 之 golang 实现

分享一下 golang 实现的 redis 和 mysql 连接池,可以在项目中直接引用连接池句柄,调用对应的方法. 举个栗子: 1 mysql 连接池的使用 (1) 在项目子目录放置 mysql.go (2)在需要调用的地方导入连接池句柄 DB (3)调用 DB.Query() 2 redis 连接池的使用 (1)在项目子目录放置 redis.go (2)在需要调用的地方导入连接池句柄 Cache (3)调用 Cache.SetString ("test_key", "te

spring 使用c3po连接池

1 数据源:能够简单理解为数据的来源. 2 连接池:是缓存一定数量的数据库连接,当程序须要数据库连接的时候,直接在连接池中获取空暇的连接,使用完再放回连接池中,此连接又变成空暇状态,等待下一次连接. 有于开启连接和关闭连接比較耗费系统资源,有类连接池的管理能够降低这方面的开支. 3 常见连接池:c3p0,dbcp,proxool是常见开源的三种连接池. Spring提供的DriverManagerDataSource总是新建一个连接,根本没有起到连接池的作用. 4 连接池获取连接的方法: Con