牛骨文教育服务平台(让学习变的简单)
博文笔记

JDBC数据库连接池实现原理(手动实现)

创建时间:2017-10-02 投稿人: 浏览次数:710
一、普通的数据库连接     如下图所示,个用户获取数据库数据都要单独建立一个jdbc连接,当用户获取数据完成后再将连接释放,可见对cpu的资源消耗很大。

 二、建立数据库连接池     数据库连接池创建后,每次获取数据库数据不需要另外建立连接,而是从连接池里拿出连接进行数据交互

 三、手动实现连接池 核心:使用线程安全的Vector容器装连接Connection(C3P0使用的是LinkedList) PoolConfig.java数据库连接池属性配置 1
/*
2
1.线程安全
3
2.有空闲连接的数量
4
3.有正在使用的连接数量
5
*/
6
public class PoolConfig{
7
    /*
8
    数据库jdbc属性
9
    */
10
    private String driverName;//数据库的驱动类
11
    private String url;//数据库的连接地址
12
    private String userName;//数据库用户名
13
    private String password;//数据库密码
14
    
15
    /*
16
    连接池配置
17
    */
18
    private int minConn = 1;//空闲集合中最少连接数
19
    private int maxConn = 5;//空闲集合最多的连接数
20
    private int initConn = 5;//初始连接数
21
    private int maxActiveConn = 10;//整个连接池(数据库)允许的最大连接数
22
    private int waitTime = 1000;//单位毫秒,连接数不够时,线程等待的时间
23
    private boolean isCheck = false;//数据库连接池是否启用自检机制(间隔一段时间检测连接池状态)
24
    private long checkPeriod = 1000*30;//自检周期
25
    
26
    //以下省略getter、setter方法...
27
}
db.properties配置文件














1

jdbc.driverName = com.mysql.jdbc.Driver
2
jdbc.url = jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncode=true&characterEncoding=utf-8
3
jdbc.userName=root
4
jdbc.password=root
DBUtil.java数据库工具包(数据库开发者调用)
1
public class DBUtil{
2
    /* 静态数据库配置实体对象,程序运行时加载进内存 */
3
    private static PoolConfig config = new PoolConfig(); 
4
    
5
    static{//初始化加载配置文件
6
        Properties prop = new Properties();
7
        try{
8
            prop.load(DBUtil.class.getClassLoader().
9
                       getResourceAsStream
10
                      ("com/mypath/db/db.properties"));
11
            //获取配置文件信息传入config连接池配置对象
12
            config.setDriverName(prop.getProperty("jdbc.driverName"));
13
            config.setUrl(prop.getProperty("jdbc.url"));
14
            config.setUserName(prop.getProperty("jdbc.userName"));
15
            config.setPassword(prop.getProperty("jdbc.password"));
16
            //反射加载这个驱动(使用的是JDBC的驱动加载方式)
17
            Class.forName(config.getDriverName());
18
        }catch(IOException e){
19
            e.printStackTrace();
20
        }
21
    }
22
    
23
    private static ConnectionPool connPool = new ConnectionPool(config);
24
    
25
    public static connection gerConnection(){
26
        return connPool.getConnection();
27
    }
28
    
29
    public static connection gerCurrentConnection(){
30
        return connPool.getCurrentConnection();
31
    }
32
    
33
    public static void closeConnection(Connection conn){
34
        connPool.releaseConnection(conn);
35
    }
36
}
ConnectionPool.java数据库连接池对象(根据配置创建对应连接池)



















1

public class ConnectionPool{
2
    private PoolConfig config;//连接池的配置对象
3
    private int count;//记录连接池的连接数
4
    private boolean isActive;//连接池是否被激活
5
    //空闲连接集合
6
    private Vector<Connection> freeConn = new Vector<Connection>();
7
    //正在使用的连接集合
8
    private Vector<Connection> userConn = new Vector<Connection>();
9
    //同一个线程无论请求多少次都使用同一个连接(使用ThreadLocal确保)
10
    //每一个线程都私有一个连接
11
    private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
12
    /*
13
    初始化连接池配置
14
    */
15
    public ConnectionPool(PoolConfig config){
16
        this.config = config;
17
    }
18
    
19
    /*
20
    数据库连接池初始化
21
    */
22
    public void init(){
23
        for(int i=0;i<config.getInitConn();i++){//建立初始连接
24
            //获取连接对象
25
            Connection conn;
26
            try{
27
                conn = getNewConnection();
28
                freeConn.add(conn);
29
                count++;
30
            }catche(SQLException e){
31
                e.printStackTrace();
32
            }
33
            isActive = true;//连接池激活
34
        }
35
    }
36
    
37
    /*
38
    获取新数据库连接
39
    */
40
    private synchronized Connection getNewConnection() throws SQLException{
41
        Connection conn = null;
42
        conn = DriverManager.getConnection(config.getUrl(),
43
                                          config.getUserName(),
44
                                          config.getPassword());
45
        return conn;
46
    }
47
    
48
    /*
49
    从连接池获取连接
50
    */
51
    public synchronized Conenction getConnection(){
52
        Connection conn = null;
53
        //当前连接总数小于配置的最大连接数才去获取
54
        if(count<config.getMaxActiveConn()){
55
            //空闲集合中有连接数
56
            if(freeConn.size()>0){
57
                conn = freeConn.get(0);//从空闲集合中取出
58
                freeConn.remove(0);//移除该连接
59
            }else{
60
                conn = getNewConnection();//拿到新连接
61
                count++;
62
            }
63
            if(isEnable(conn)){
64
                useConn.add(conn);//添加到已经使用的连接
65
            }else{
66
                count--;
67
                conn = getConnection();//递归调用到可用的连接
68
            }
69
        }else{//当达到最大连接数,只能阻塞等待
70
            wait(config.getWaitTime());//线程睡眠了一段时间
71
            conn = getConnection();//递归调用
72
        }catch(Exception e){
73
            e.printStackTrace();
74
        }
75
        //将获取的conn设置到本地变量ThreadLocal
76
        threadLocal.set(conn);
77
        return conn;
78
    }
79
    
80
    /*
81
    把用完的连接放回连接池集合Vector中
82
    */
83
    public synchronized void releaseConnection(Connection conn){
84
        if(isEnable(conn)){
85
            if(freeConn.size()<config.getMaxConn()){//空闲连接数没有达到最大
86
                freeConn.add(conn);//放回集合
87
            }else{
88
                conn.close();
89
            }
90
        }
91
        useConn.remove(conn);
92
        count--;
93
        threadLocal.remove();
94
        notifyAll();//放回连接池后说明有连接可用,唤醒阻塞的线程获取连接
95
    }
96
    
97
    /*
98
    获取当前线程的本地变量连接
99
    */
100
    public Connection getCurrentConnection(){
101
        return threadLocal.get();    
102
    }
103
    
104
    /*
105
    判断该连接是否可用
106
    */
107
    private boolean isEnable(Connection conn){
108
        if(conn == null){
109
            return false;
110
        }
111
        if(conn.isClosed()){
112
            return false;
113
        }
114
        return true;
115
    }
116
}
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。