手写数据库连接池

几个概念:
1、初始化连接数,比如存在5个Connection
2、最大连接数,比如最大10个Connection
3、空闲池,存放当钱没有被使用的connection
4、活动池,存放当前正在使用的connection
5、执行完业务逻辑后,进行连接的释放,即放入空闲池
6、数据库本身也对连接数有一定的限制,比如MySql同时允许最大连接100个

初始化时生成的默认连接数放置在空闲连接池中。
容器必须是线程安全的,并发操作连接对象。(从空闲池到活动池)


注意几个点:
当connection使用完成之后,需要重新放置到空闲池里面。
空闲池和活动池必须是线程安全的
获取连接时,当检测到活动池中的connection数量已经超过最大连接数,则进行重新获取(递归调用)。

从空闲连接池中获取连接实例后,需要把该实例添加至活动空闲池中,同时删除空闲池中的记录


配置类:手动添加一下setter和getter方法

package pool;
/**
 * Created by 156 on 2019/3/28.
 *
 * 需要 MySql-connect 5.x版本
 */
public class DbBean {

    /* 链接属性 */
    private String driverName = "com.mysql.jdbc.Driver";
    private String url = "jdbc:mysql://localhost:3306/spring5";
    private String userName = "root"
    private String password = "123456";
    private int minConnections = 1; // 空闲池,最小连接
    private int maxConnections = 10; // 空闲池,最大连接数
    private int initConnections = 5;// 初始化连接数
}

 

连接池

 

    package pool;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.util.List;
    import java.util.Vector;
    
    /**
     * Created by 156 on 2019/3/28.
     */
    public class ConnectionPool implements IConnectionPool
    {
    
        public void setFreeConnection(List<Connection> freeConnection) {
            this.freeConnection = freeConnection;
        }
    
        // 空闲线程集合
        private List<Connection> freeConnection = new Vector<Connection>();
    
        // 活动线程集合
        private List<Connection> activeConnection = new Vector<Connection>();
    
    
        private DbBean dbBean;
    
        public ConnectionPool(DbBean dbBean) throws Exception
        {
            this.dbBean = dbBean;
            init();
        }
    
        public void init() throws Exception
        {
            //  根据初始化的连接数,进行创建Connection实例
            for (int i = 0; i < dbBean.getInitConnections(); i++)
            {
                Connection instance = createConn();
                if (null != instance )
                {
                    freeConnection.add(instance); //  将创建的实例添加至空闲池中
                }
            }
        }
        // 创建新的Connection
        private Connection createConn()
        {
            try
            {
                if (null == dbBean)
                {
                    return null;
                }
                Class.forName(dbBean.getDriverName());
                Connection connection = DriverManager.getConnection(dbBean.getUrl(), dbBean.getUserName(),
                        dbBean.getPassword());
                return connection;
            } catch (Exception e) {
                return null;
            }
    
        }
    
        /***
         * 获取connecton
         * 1、首先判断空闲池中是否还有connection实例
         * 2、当空闲池线中没有connection实例时,
         *      判断当前活动线程池中存在的connection数目是否大于最大connection数目
         *
         *
         * @return
         */
        public Connection getConnection()
        {
            Connection connection = null;
    
            //  说明空闲池中还有未使用的connection实例,直接返回
            //  不需要记录该connectio获取的动作
            if (freeConnection.size()>0)
            {
                //  1、备份需要返回的connection
                Connection reConn = freeConnection.get(0);
                //  判断当前连接是否可用
                if(!isAvailable(reConn)){
                    return null;
                }
                // 2、从空闲连接池中移除
                freeConnection.remove(0);
                // 3、添加至活动连接池中
                activeConnection.add(reConn);
                return reConn; //  返回一个connection实例
            }
            // 当前活动connection实例数目小于配置的最大数目时,进行新实例的创建
            //  在返回一个Connection实例的同时,同时记录一下新生成的connection
            if ( activeConnection.size()<dbBean.getMaxConnections())
            {
                // 1、重新生成连接
                Connection newC = createConn();
                //  判断当前连接是否可用
                if(!isAvailable(newC)){
                    return null;
                }
                // 2、记录一下新生成的connection
                activeConnection.add(newC);
                return createConn();
            }
            // 当前活动的connection实例已经大于最大数目,则进行重新获取
            if(activeConnection.size()>dbBean.getMaxConnections())
            {
               return getConnection();
            }
    
            return null;
        }
    
        public void releaseConnection(Connection connection)
        {
            try
            {
                if (connection == null)
                {
                    return;
                }
                if (isAvailable(connection))
                {
                    // 判断空闲线程数是否大于最大线程数
                    if (freeConnection.size() < dbBean.getMaxConnections())
                    {
                        freeConnection.add(connection);
                    }
                }
    
            } catch (Exception e) {
    
            }
        }
    
        // 判断连接是否可用
        public boolean isAvailable(Connection connection) {
            try {
                if (connection == null || connection.isClosed()) {
                    return false;
                }
    
            } catch (Exception e) {
                // TODO: handle exception
            }
            return true;
    
        }
    
    }

 

测试

 @Test
    public void test() throws Exception {

        ConnectionPool connectionPool = new ConnectionPool(new DbBean());

        for (int i=1;i<=11;i++){

            System.out.println(i+"===>"+connectionPool.getConnection());

        }
    }

 

posted @ 2020-02-09 14:22  xinjia  阅读(193)  评论(0编辑  收藏  举报