手撸一个数据库连接池

需求由来

(1)sql都是依靠jdbc提供的connection .execute(sql)执行的,获取connection 途径:
Connection connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
但是一个connection同时只能被一个线程执行excute(),否则可能存在竞态条件

(2)connection的创建是比较消耗资源,所以可以创建一个装connection的“池”,存入一些实例化好的connection,需要的时候从池中取出,使用完成后释放到池中

池的功能点

(1)持有一个connection的容器
(2)创建connection
(3)获取connection
(4)释放connection
(5)保证每次获取connection都是竞态安全的
 

注意问题

(1)创建connection、获取connection应该保证pooledConnections的线程安全,所以需要使用synchronized的如【一】【二】
(2)释放connection只需要将PooledConnection isBusy 设置为false即可,由于connection被独立线程持有,所以释放不存在竞态条件【三】;设置为busy状态是从连接池中获取,所以应当由连接池保证竞态安全【四】

 

代码片段
public class PooledConnection {
    private Connection connection;
    private boolean isBusy = false;

  【三】
    public void closeConnection(){
         // PooledConnection 线程独立,可以自己修改isBusy状态
        isBusy =false;
    }
}

public class DefaultPool implements Pool{

    private Vector<PooledConnection> pooledConnections = new Vector<>();
    String jdbcUrl;
    String jdbcUsername;
    String jdbcPassword;
    int initCount;
    int step;
    int maxCount;

    public DefaultPool() {

        try{
            Class.forName(Conf.jdbcDriver);
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }

        createPooledConnection(initCount);
    }

    @Override
    public PooledConnection getPooledConnection() {
      
        PooledConnection pooledConnection = getRealConnctionFromPool();
        while (pooledConnection == null){
            return createPooledConnection(step);
        }
        return pooledConnection;
    }

    【一】
   @Override
    public synchronized PooledConnection createPooledConnection(int count) {

        if(pooledConnections.size() > maxCount){
            throw new RuntimeException("线程池已满");
        }

        PooledConnection pooledConnection = null;
        for(int i = 0; i < count ; i++){
            try{
                Connection connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
                pooledConnection = new PooledConnection(connection, false);
                pooledConnections.add(pooledConnection);
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        return pooledConnection;
    }

【二】
    private synchronized PooledConnection getRealConnctionFromPool(){
        for(PooledConnection pooledConnection : pooledConnections){
            // 可能会出现脏读,因为releaseConnect()更新的值,可能还没有刷到共享缓存
            if(pooledConnection.isBusy()){
                continue;
            }

            try{

                if(pooledConnection.getConnection().isValid(3000)){
                    // 使用busy来标志连接是否可用的
                    pooledConnection.setBusy(true);
                    return pooledConnection;
                }

                Connection connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
                pooledConnection.setConnection(connection);
                【四】
                pooledConnection.setBusy(true);
                return pooledConnection;
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        // 返回为空的潜台词就是要准备创建新的连接了
        return null;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值