• 简单数据库连接池-总结


    一、代码实现

    //参数配置类
    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 放在释放类中,当一个线程释放连接后,则换新其他线程获取连接(省去了等待的时间)

  • 相关阅读:
    2015 10月21日 工作计划与执行
    2015 10月20日 工作计划与执行
    2015 10月19日 工作计划与执行
    排序算法之归并排序 分类: C/C++ 数据结构与算法 2015-06-29 16:46 190人阅读 评论(0) 收藏
    sublime个人配置(C++程序员) 分类: C/C++ 2015-06-29 09:29 95人阅读 评论(0) 收藏
    排序算法之简单排序 分类: C/C++ 2015-06-29 08:14 252人阅读 评论(0) 收藏
    profile与bashrc 分类: Ubuntu学习笔记 2015-06-26 14:42 146人阅读 评论(0) 收藏
    leetCode(26):Unique Binary Search Trees 分类: leetCode 2015-06-23 14:09 155人阅读 评论(0) 收藏
    leetCode(25):Validate Binary Search Tree 分类: leetCode 2015-06-23 13:00 154人阅读 评论(0) 收藏
    leetCode(24):Binary Search Tree Iterator 分类: leetCode 2015-06-23 11:50 192人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/lufei33180/p/13406476.html
Copyright © 2020-2023  润新知