自定义数据结构设计JDBC连接池提高性能

// 后面贴上源码

之前写一个小工具,发现了一个问题,发现部署到云计算上面,由于需要操作其他环境的数据库,发现获取66   175环境的获取连接非常缓慢。

通过打印日志,然后部署到服务器,发现获取175环境的数据库连接池居然要6s?? 获取66环境需要3s 显然不合理?



 


一个查询居然要5-6秒,具体原因我真的不懂,为啥175连的那么困难? 是不是物理机隔得太远了?还是啥。。 反正想着既然这样,

本来想用业界成熟的c3p0,或者本平台已经在使用的阿里巴巴druid连接池,但是好像不太符合我们的需求。因为我们需要保存很多个不同环境的连接,数据结构不能是List单纯保存连接,需要一个map映射。

最后自己写一个自定义连接池吧。。。 把获取到的连接保存到集合里,不需要就放回去,需要在拿回来,这是最简单的思路,就开始编码了,看看能不能解决问题。

思路大概这样吧:


 

注意要给释放连接和获取连接加上重入锁,保证多线程的可靠性。

最后从新部署测试。



 

----------遗留问题,一直不明白为什么jdbc建立connection连接 对于66环境和175环境需要3-5s, 而其他环境建立连接就算不用连接池只需要几ms。

最后附上代码

package com.huawei.solution.utils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

import static com.huawei.solution.constants.CommonConstants.PASS_WORD;
import static com.huawei.solution.constants.CommonConstants.USER_NAME;
import static com.huawei.solution.constants.CommonConstants.DRIVER_CLASS_NAME;

/**
 * @ClassNme DataSourcePoolNew
 * @Author x84104122
 * @Date 2018/10/29 17:45
 * @Description  自定义简单数据库映射连接池
 */
public class DataSourcePoolNew {
    /**
     * 最大连接数
     */
    private static final int COUNT = 10;
    /**
     * 存放数据库
     * key 为环境 value 为数据库
     */
    public static final Map<Integer, LinkedList<Connection>> connections = new ConcurrentHashMap<>();
    /**
     * 创建锁
     */
    private static final ReentrantLock lock = new ReentrantLock();
    private static final Condition notEmpty = lock.newCondition();
    private static final Condition notFull = lock.newCondition();
    /**
     * 数据库连接
     */
    private static String URL;


    public DataSourcePoolNew() {
    }

    /**
     * 初始化信息
     */
    public DataSourcePoolNew(Integer key,String url) {
        final ReentrantLock reentrantLock = lock;
        reentrantLock.lock();
        try {
            //加载驱动
            URL = url;
            Class.forName(DRIVER_CLASS_NAME);
            LinkedList<Connection> connectionList = new LinkedList<>();
            for (int i = 0; i < COUNT; i++) {
                Connection connection = DriverManager.getConnection(URL, USER_NAME, PASS_WORD);
                connectionList.add(connection);
            }
            connections.put(key, connectionList);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            reentrantLock.unlock();
        }
    }


    /**
     * 获取Connection
     */
    public Connection getConnection(Integer key) {
        if (!connections.containsKey(key)){
            return null;
        }
        final ReentrantLock reentrantLock = lock;
        reentrantLock.lock();
        try {
            //如果没有连接了,则等待着新放入的连接
            if (connections.get(key).isEmpty()) {
                notEmpty.await();
            }
            Connection connection = connections.get(key).removeFirst();
            notFull.signalAll();
            return connection;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            reentrantLock.unlock();
        }
        return null;
    }

    /**
     * 释放连接
     *
     * @param connection
     */
    public static void release(Integer key, Connection connection) {
        if (!connections.containsKey(key)){
            return ;
        }
        final ReentrantLock reentrantLock = lock;
        reentrantLock.lock();
        try {
            if (connections.get(key).size() == COUNT) {
                notFull.await();
            }
            if (connection == null || connection.isClosed()) {
                connections.get(key).add(DriverManager.getConnection(URL, USER_NAME, PASS_WORD));
                notEmpty.signalAll();
                return;
            }
            //恢复默认值
            if (connection.getAutoCommit() == false) {
                connection.setAutoCommit(true);
            }
            connections.get(key).add(connection);
            notEmpty.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            reentrantLock.unlock();
        }
    }
}

使用Demo

获取连接 

if (DataSourcePoolNew.connections.containsKey(environment) && !DataSourcePoolNew.connections.get(environment).isEmpty()) {
    con = DataSourcePoolNew.connections.get(environment).removeFirst();
} else {
    con = new DataSourcePoolNew(environment, url).getConnection(environment);
}

释放连接

放回集合了

DataSourcePoolNew.release(environment, con);

本文主要给大家提供一个思路,深入理解连接池。大家可以自己自定义自己想要的数据结构模型,去获取相应的数据库连接池。代码是活的,思路是死的。

猜你喜欢

转载自blog.csdn.net/xmh594603296/article/details/83619513