Java手写连接池

  1. .连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用。也是复用连接。
  2. 连接池简易设计图
    这里写图片描述

  3. 代码

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/njdx?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=root
jdbc.maxActive=50
jdbc.initialSize=5
jdbc.stepSize = 5
/**
 * 连接池方法接口
 *
 * @Author yjian
 * @Date 16:08 2017/10/14
 **/
public interface IDataBasePool {

    //对外提供管道
    PooledConnection getConnection();

    //对内创建链接
    void createConnections(int count);

}
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import java.util.Vector;

/**
 * 连接池实现
 *
 * @Author yjian
 * @Date 16:40 2017/10/14
 **/
public class DataBasePoolImpl implements IDataBasePool {

    //源代码中的所有参数属性都是对外的配置
    private static String driver = null;
    private static String url = null;
    private static String user = null;
    private static String password = null;

    //限制连接池中的管道数量参数
    private static int initCount = 4;
    private static int stepSize = 10;
    private static int poolMaxSize = 150;
    //线程安全的集合 用来放我们的连接管道
    private static Vector<PooledConnection> pooledConnections = new Vector<PooledConnection>();

    public DataBasePoolImpl() {
        init();
    }

    /**
     * 初始化 解析配置文件并创建连接池
     *
     * @Author yjian
     * @Date 16:33 2017/10/14
     **/
    public void init() {
        //获得连接池配置并读取
        InputStream input = this.getClass().getClassLoader().getResourceAsStream("jdbc.properties");
        Properties properties = new Properties();
        try {
            properties.load(input);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //解析数据
        driver = properties.getProperty("jdbc.driverClassName");
        url = properties.getProperty("jdbc.url");
        user = properties.getProperty("jdbc.username");
        password = properties.getProperty("jdbc.password");
        //对字节信息进行判断
        if (Integer.valueOf(properties.getProperty("jdbc.initialSize")) > 0) {
            initCount = Integer.valueOf(properties.getProperty("jdbc.initialSize"));
        }
        if (Integer.valueOf(properties.getProperty("jdbc.maxActive")) > 0) {
            poolMaxSize = Integer.valueOf(properties.getProperty("jdbc.maxActive"));
        }
        if (Integer.valueOf(properties.getProperty("jdbc.stepSize")) > 0) {
            stepSize = Integer.valueOf(properties.getProperty("jdbc.stepSize"));
        }
        //准备创建什么类型管道
        try {
            //反射
            Driver dbDriver = (Driver) Class.forName(driver).newInstance();
            //注册
            DriverManager.registerDriver(dbDriver);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //开始创建连接池
        createConnections(initCount);
    }

    /**
     * 从连接池获取有效的连接,如果没有会容错创建
     *
     * @Author yjian
     * @Date 16:31 2017/10/14
     **/
    public PooledConnection getRealConnection() {
        for (PooledConnection conn : pooledConnections) {
            if (!conn.isBuy()) {
                //获得物理连接
                Connection connection = conn.getConnection();
                try {
                    //发送一个指令给数据库,看是否收到回应
                    if (!connection.isValid(2000)) {
                        connection = DriverManager.getConnection(url, user, password);
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                //设置当前连接被占用
                conn.setBuy(true);
                return conn;
            }
        }
        return null;
    }

    @Override
    public PooledConnection getConnection() {
        //容错性校验
        if (pooledConnections.size() == 0) {
            System.out.println("获取数据库连接管道失败");
            //手动刷新
            createConnections(initCount);
        }
        PooledConnection pooled = getRealConnection();
        while (pooled == null) {
            createConnections(stepSize);
            pooled = getRealConnection();
            //防止被其他人抢了
            try {
                Thread.sleep(20);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return pooled;
    }

    @Override
    public void createConnections(int count) {
        //判断是否超过连接池最大限制
        if (pooledConnections.size() + count <= poolMaxSize) {
            for (int i = 0; i < initCount; i++) {
                try {
                    //创建连接
                    Connection connection = DriverManager.getConnection(url, user, password);
                    //封装
                    PooledConnection pooled = new PooledConnection(false, connection);
                    //加入连接池
                    pooledConnections.add(pooled);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                System.out.println("初始化" + (i + 1) + "个管道");
            }
        } else {
            System.out.println("超过连接池最大限制");
        }
    }
}
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

/**
 * 连接池实体
 */
public class PooledConnection {

    //标识繁忙标识 复用的标志 线程安全
    private boolean isBuy = false;

    //物理连接(连接数据库的)
    private Connection connection;

    //数据库操作
    public ResultSet queryBySql(String sql) {
        Statement sm = null;
        ResultSet rs = null;
        try {
            sm = connection.createStatement();
            rs = sm.executeQuery(sql);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return rs;
    }
    //这个功能也是自定义添加  是否链接
    public void close() {
        this.isBuy = false;
    }

    public PooledConnection(boolean isBuy, Connection connection) {
        this.isBuy = isBuy;
        this.connection = connection;
    }

    public boolean isBuy() {
        return isBuy;
    }

    public void setBuy(boolean buy) {
        isBuy = buy;
    }

    public Connection getConnection() {
        return connection;
    }

    public void setConnection(Connection connection) {
        this.connection = connection;
    }
}
/**
 * 内部类单列模式
 *
 * @Author yjian
 * @Date 16:40 2017/10/14
 **/
public class DataBaseSingleton {

    private static class createDataBasePool {
        private static DataBasePoolImpl poolImp = new DataBasePoolImpl();
    }

    /**
     * 内部类单列模式,仿造类加载原理完美实现线程安全问题 JDK加载时内部类,线程互斥保证了线程安全
     *
     * @Author yjian
     * @Date 16:37 2017/10/14
     **/
    public static DataBasePoolImpl getInstace() {
        return createDataBasePool.poolImp;
    }

}
import java.sql.ResultSet;


/**
 * 连接池测试类
 *
 * @Author yjian
 * @Date 16:39 2017/10/14
 **/
@SuppressWarnings("ALL")
public class DataBasePoolTest {

    //内部类单例模式
    private static DataBasePoolImpl poolImpl = DataBaseSingleton.getInstace();

    public synchronized static void selectData() {
        //获取连接池
        PooledConnection connection = poolImpl.getConnection();
        ResultSet rs = connection.queryBySql("select * from test");
        System.out.println("线程名称:" + Thread.currentThread().getName());
        try {
            while (rs.next()) {
                System.out.println(rs.getInt("id"));
                System.out.println(rs.getString("name"));
                System.out.println(rs.getString("nums"));
                System.out.println();
            }
            //释放
            rs.close();
            //释放当前连接
            connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
        for (int i = 0; i < 1500; i++) {
            new Thread(new Runnable() {
                public void run() {
                    selectData();
                }
            }).start();
        }
    }
}

版权声明:本文为yingfengjia520原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。