简单数据库连接池-总结

一、代码实现

//参数配置类
public class DbBean {
    private String driverName="com.mysql.jdbc.Driver"; //数据库驱动名称
    private String url="jdbc:mysql://localhost:3306/iodn";//数据库连接地址
    private String username="root";//用户名
    private String userpwd="odn2018";//密码
    private String poolName="thread01";//池名
    private int minConnection=1;//最小连接数
    private int maxConnection=5;//最大连接数
    private int initConnection=3;//初始化连接数
    private long connectOut=100000;//重试连接的时间
    private int maxActiveConnection=100;//最大可连接的数量
    private long connectOverOut=60*1000;//连接超时时间
}
//连接池业务逻辑类
public class ConnectionPool {
    private List<Connection> freeConnection=new Vector<>();
    private List<Connection> activeConnection=new Vector<>();
    private DbBean dbBean;
    private int connectionCount=0;
    public ConnectionPool(DbBean dbBean){
        this.dbBean=dbBean;
        init();
    }

    //连接池初始化方法
    private void init() {
        if(dbBean==null){
            throw new RuntimeException("数据库初始化参数不能为空");
        }
        for(int i=0;i<dbBean.getInitConnection();i++){
            Connection newConnection=newConnection();
            if(newConnection!=null){
                System.out.println("初始化添加到空闲池");
                freeConnection.add(newConnection);
                System.out.println("空闲池大小"+freeConnection.size());
            }
        }
    }

    //数据库创建连接
    public Connection newConnection() {
        System.out.println("新建一个连接");
        try {
            Class<?> connectionClass= Class.forName(dbBean.getDriverName());
            Connection connection= DriverManager.getConnection(dbBean.getUrl(),dbBean.getUsername(),dbBean.getUserpwd());
            return connection;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //数据库获取连接
    public synchronized  Connection getConnection(){

        Connection connection = null;
        if(connectionCount<dbBean.getMaxConnection()){//小于最大的连接数
            if(freeConnection.size()>0){
                connection=freeConnection.remove(0);
            }else{
                connection=newConnection();
            }
            if(isAvailable(connection)){
                activeConnection.add(connection);
                connectionCount++;
            }else{
                getConnection();
            }

        }else {
            try {
                System.out.println("等待重新获取,已经连接数="+connectionCount);
                wait(dbBean.getConnectOut());
                connection=getConnection();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName()+"开始获取连接,连接总数:"+connectionCount);
        System.out.println(Thread.currentThread().getName()+"开始获取空闲连接数:"+freeConnection.size());
        System.out.println(Thread.currentThread().getName()+"开始获取正在使用连接数:"+activeConnection.size());
        return  connection ;
    }

    private boolean isAvailable(Connection connection) {
        try {
            if(connection==null ||connection.isClosed()){
                return false;
            }
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public synchronized void  releaseConnection(Connection connection){



        if(isAvailable(connection)){
            try {
                if(freeConnection.size()<dbBean.getInitConnection()){
                    freeConnection.add(connection);
                }else{
                    System.out.println("空闲数超过默认初始化值");
                    connection.close();
                }
                connectionCount--;
                activeConnection.remove(connection);
                System.out.println(Thread.currentThread().getName()+"开始释放正在使用连接数:"+activeConnection.size());
                System.out.println(Thread.currentThread().getName()+"开始释放空闲连接数:"+freeConnection.size());
                System.out.println(Thread.currentThread().getName()+"开始释放连接,连接总数:"+connectionCount);
               notifyAll();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
}

//连接池入口管理类
public class ConnectionPoolManager {
    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);
    }
}

//多线程测试类
public class ThreadConnect implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i <8; i++) {
            Connection connection=ConnectionPoolManager.getConnection();
            System.out.println(Thread.currentThread().getName()+",connection:"+connection);
            ConnectionPoolManager.releaseConnection(connection);
        }
    }
}

//测试类
public class Test {
    public static void main(String[] args) throws InterruptedException {
        Long startTime=System.currentTimeMillis();
        for(int i=0;i<40;i++){
            Thread thread=new Thread(new ThreadConnect());
            thread.start();
        }
        Thread.sleep(3000);
        Long endTime=System.currentTimeMillis();
        System.out.println("共耗时"+(endTime-startTime));

    }
}

二、总结

1、数据库连接池主要包含 参数配置类、连接池类、管理类以及测试类,连接池主要负责默认连接的初始化(池中默认已经创建的连接),连接的获取和连接的释放,连接主要的实现逻辑为,如果空闲连接池中有,则直接从池中获取连接,如果空闲池中没有,则创建新的连接(不超过最大连接,超过则等待其他线程释放)

2、连接池获取和释放线程用到了wait notify notifyAll 方法,用来控制线程因长时间等待而轮询获取连接,notityall 放在释放类中,当一个线程释放连接后,则换新其他线程获取连接(省去了等待的时间)

posted @ 2020-07-30 21:35  狭路相逢智者胜  阅读(161)  评论(0编辑  收藏  举报