手写一个简易数据库连接池

数据库连接池,一般用于后台应用与后台数据库的交互,其目的主要是控制服务器资源消耗,常用的有Druid、C3P0、Hikari。

为了对数据库连接池有一个更深入的了解,我们手写一个简易连接池。

其具体步骤如下:

核心参数:
空闲线程数 freeConnectPool
活动线程数 activeConnectPool

原理:
1.根据配置文件参数,初始化连接池,设置初始线程数
2.通过getConnection(),获取连接,如果空闲线程大于0,则直接从空闲线程取连接,此时freeConnectPool计数减1,activeConnectPool计数加1;
否则需要判断当前线程连接是否达到最大连接数,如果达到,则wait()之后,继续调用getConnection(),
如果当前线程连接未达到最大连接数,则直接新建一个连接,并放入activeConnectPool。
3.通过releaseConnection(),释放当前连接。如果freeConnectPool已满,证明空闲线程足够多,直接关闭此连接;
如果freeConnectPool还未满,则装入空闲线程池中。

定义数据库配置POJO类:

package com.jdbc;

public class DbBean {

    /* 链接属性 */
    private String driverName = "com.mysql.cj.jdbc.Driver";

    private String url = "jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=UTC";

    private String userName = "root";

    private String password = "123456";

    private String poolName = "thread01";// 连接池名字

    private int minConnections = 1; // 空闲池,最小连接数

    private int maxConnections = 10; // 空闲池,最大连接数

    private int initConnections = 5;// 初始化连接数

    private long connTimeOut = 1000;// 重复获得连接的频率

    private int maxActiveConnections = 100;// 最大允许的连接数,和数据库对应

    private long connectionTimeOut = 1000 * 60 * 20;// 连接超时时间,默认20分钟



}

定义连接池接口:

package com.jdbc;

import java.sql.Connection;

public interface IConnectionPool {

    Connection getConnection();

    void releaseConnection(Connection connection);

}

实现连接池逻辑:

package com.jdbc;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Vector;

/*
title:手写数据库连接池
步骤:
核心参数:
空闲线程数 freeConnectPool
活动线程数 activeConnectPool
1.根据配置文件参数,初始化连接池,设置初始线程数
2.通过getConnection(),获取连接,如果空闲线程大于0,则直接从空闲线程取连接,此时freeConnectPool计数减1,activeConnectPool计数加1;
否则需要判断当前线程连接是否达到最大连接数,如果达到,则wait()之后,继续调用getConnection(),
如果当前线程连接未达到最大连接数,则直接新建一个连接,并放入activeConnectPool。
3.通过releaseConnection(),释放当前连接。如果freeConnectPool已满,证明空闲线程足够多,直接关闭此连接;
如果freeConnectPool还未满,则装入空闲线程池中。
 */
public class ConnectionPool implements IConnectionPool {

    //线程安全集合
    private List<Connection> freeConnectPool = new Vector<>();

    private List<Connection> activeConnectPool = new Vector<>();

    private DbBean dbBean;

    int count = 0;//计算最大连接数

    public ConnectionPool(DbBean dbBean) {
        //初始化连接池
        this.dbBean = dbBean;
        initPool();

    }

    @Override
    public synchronized Connection getConnection() {
        //空闲线程存在空闲连接
        Connection connection = null;
        if (freeConnectPool.size() > 0) {
            connection = freeConnectPool.remove(0);
            activeConnectPool.add(connection);
        } else {
            //判断当前线程连接数量是否达到最大值
            if (count < dbBean.getMaxActiveConnections()) {
                connection = createConnection();
                activeConnectPool.add(connection);
                count++;
            }else {
                try {
                    wait(dbBean.getConnTimeOut());//活动线程已满等待解封
                    connection = getConnection();//递归调用
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    return null;
                }
            }
        }
        return connection;
    }

    @Override
    public synchronized void releaseConnection(Connection connection) {
       //如果空闲线程数已满,证明连接足够多
        if(freeConnectPool.size() < dbBean.getMaxConnections()){
            freeConnectPool.add(connection);
        }else{
            try {
                //此时维持线程只有10个
                connection.close();
                activeConnectPool.remove(connection);
                count--;
                notifyAll();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }

    private void initPool() {
        if (dbBean == null) {
            throw new RuntimeException("配置文件为空");
        }
        for (int i = 0; i < dbBean.getInitConnections(); i++) {
            //新建连接
            Connection connection = createConnection();
            if (null != connection) {
                freeConnectPool.add(connection);
                count++;
            }
        }
    }

    private Connection createConnection() {
        /*
         * 注册jdbc驱动
         * */
        Driver driver = null;
        Connection connection = null;
        try {
            driver = (Driver) Class.forName(dbBean.getDriverName()).newInstance();
            DriverManager.registerDriver(driver);
            connection = DriverManager.getConnection(dbBean.getUrl(), dbBean.getUserName(), dbBean.getPassword());
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }
}

管理数据库连接池:

package com.jdbc;

import java.sql.Connection;

public class ManageConnection {

    private static DbBean dbBean = new DbBean();
    private static ConnectionPool connectionPool = new ConnectionPool(dbBean);

    public static Connection getConnection(){
        return connectionPool.getConnection();
    }

    public static void releaseConnection(Connection connection){
        connectionPool.releaseConnection(connection);
    }
}

测试连接池:

package com.jdbc;

import java.sql.Connection;

public class TestConnection {

    public static void main(String[] args) {
        PoolThread poolThread = new PoolThread();
        for (int i = 0; i < 5; i++) {
            Thread thread = new Thread(poolThread,"线程"+i);
            thread.start();
        }

    }
}

class PoolThread implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            Connection connection = ManageConnection.getConnection();
            System.out.println("当前线程:"+Thread.currentThread().getName()+"connection: "+connection);
            ManageConnection.releaseConnection(connection);
        }

    }
}

  • 7
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值