简单jdbc连接池

1. [代码]连接池类     

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package com.sli.util;
 
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;
 
public class DataSourcePool {
 
    static int connectionCurrLink = 0;
    static Map<String, String> map = null;
    private static LinkedList<Connection> datasourcePool = new LinkedList<Connection>();
    // 通过静态代码块注册数据库驱动,保证注册只执行一次
    static {
        map = new HashMap<String, String>();
        Properties p = new Properties();
        try {
            p.loadFromXML(new FileInputStream("src\\DataSourcePool.xml"));
            Enumeration<Object> dataSourceSet = p.keys();
            while (dataSourceSet.hasMoreElements()) {
                String key = (String) dataSourceSet.nextElement();
                map.put(key, p.getProperty(key));
            }
            Class.forName(map.get("conectionDriver"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    public DataSourcePool() throws Exception {
        createConnection(0);
        // 通过构造函数启动定时器以达到定时释放空闲连接目的
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                try {
                    // 得到空闲连接,datasourcePool里面有几个对象就表示有几个空闲连接
                    int leisureLink = DataSourcePool.datasourcePool.size();
                    System.out.println(leisureLink);
                    // 最小连接数
                    int connectionMinLink = Integer.parseInt(DataSourcePool.map
                            .get("connectionMinLink"));
                    // 当空闲连接大于DataSourcePool设置的最小连接数时则关闭
                    if (leisureLink > connectionMinLink) {
                        for (int i = 0; i < leisureLink - connectionMinLink; i++) {
                            DataSourcePool.closeConnection(DataSourcePool.getConnection());
                            connectionCurrLink--;
                        }
                    } else {
                        System.out.println("保持最小连接,将继续保持连接池");
                    }
                } catch (NumberFormatException e) {
                    throw new NumberFormatException("设置了无效的最小连接数");
                } catch (SQLException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, 0, Long.parseLong(map.get("connectionTimer")));
 
    }
 
    // 创建连接
    private static void createConnection(int type) throws Exception {
        try {
            int link = 0;
            switch (type) {
            case 0:
                link = Integer.parseInt(map.get("connectionMinLink"));
                break;
            case 1:
                //如果当前连接+增长连接大于设定的最大连接数时,将使用最大连接数-当前连接的数量。
                //以保持平衡
                link = Integer.parseInt(map.get("connectionIncreaseLink"));
                int maxLink = Integer.parseInt(map.get("conectionMaxLink"));
                if (link + connectionCurrLink > maxLink) {
                    link = maxLink - connectionCurrLink;
                }
                break;
            }
            for (int i = 0; i < link; i++) {
                datasourcePool.addLast(DriverManager.getConnection(map.get("connectionUrl"),
                        map.get("connectionName"), map.get("connectionPassword")));
                connectionCurrLink++;
            }
        } catch (NumberFormatException n) {
            throw new NumberFormatException("配置连接参数有误");
        } catch (Exception e) {
            e.printStackTrace();
            throw new SQLException("超过最大连接数 ,无法创建更多连接");
        }
    }
 
    // 获得连接
    public static Connection getConnection() throws Exception {
        // 取连接加锁,防止并发取的同样的连接
        synchronized (datasourcePool) {
            if (datasourcePool.size() > 0) {
                return datasourcePool.removeFirst();
            } else if (connectionCurrLink < Integer.parseInt(map.get("conectionMaxLink"))) {
                createConnection(1);
                return datasourcePool.removeFirst();
            }
        }
        return null;
    }
 
    /**
     * 关闭连接
     *
     * @param con
     * @throws SQLException
     */
    public static void closeConnection(Connection con) throws SQLException {
        con.close();
    }
 
    // 释放连接
    public void freeConnection(Connection con) {
        datasourcePool.addLast(con);
    }
 
}

2. [代码]jdbcUtil作为封装连接池的辅助类     

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.sli.util;
 
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
 
/**
 *
 * @author 罗盛力 模拟连接池(封装连接池)
 */
public final class JDBCUtil {
    private static DataSourcePool dsp = null;
 
    public JDBCUtil() throws Exception {
         
    }
 
    /**
     * 获得连接
     * @return
     * @throws Exception
     */
    public static Connection getConnection( ) throws Exception {
        if (dsp == null) {
            synchronized (DataSourcePool.class) {
                if (dsp == null) {
                    dsp = new DataSourcePool();
                }
            }
        }
        return dsp.getConnection();
    }
 
    // 关闭连接
    public static void freeConnection(ResultSet rs, Statement ps, Connection con)
            throws SQLException {
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (ps != null) {
                    ps.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (con != null) {
                    dsp.freeConnection(con);
                }
            }
        }
    }
    // 关闭连接
        public static void freeConnection(Connection con)
                throws SQLException {
                    if (con != null) {
                        dsp.freeConnection(con);
                    }
        }
      
}

3. [代码]测试类     

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.sli.test;
 
import java.sql.Connection;
 
import com.sli.util.JDBCUtil;
 
public class TestDataPool {
    public static void main(String[] args) throws Exception {
        long start = System.currentTimeMillis();
        int j=0;
        System.out.println("连接池开始:" + start);
        for (int i = 0; i <20; i++) {
            Connection con = JDBCUtil.getConnection();
            System.out.println(con);
            if(i<14) {
                JDBCUtil.freeConnection(con);
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("连接池结束:" + end);
        System.out.println("连接池耗时:" + (end - start));
    }
}

4. [代码]配置连接xml     

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"
<properties>
   <!-- 连接url -->
   <entry key="connectionUrl">jdbc:mysql:///test</entry> 
   <!-- 用户名 -->
   <entry key="connectionName">root</entry> 
   <!-- 密码 -->
   <entry key="connectionPassword">sli</entry> 
   <!-- 最小连接数(首次以此值为创建连接数标准及空闲连接大于该数时则会清除) -->
   <entry key="connectionMinLink">5</entry>
   <!-- 最大连接数 -->
   <entry key="conectionMaxLink">89</entry>
    <!-- 驱动 -->
   <entry key="conectionDriver">com.mysql.jdbc.Driver</entry>
   <!--  当连接不够用时的增长率-->
   <entry key="connectionIncreaseLink">10</entry>
   <!--  设定自动清除空闲连接时间(毫秒)-->
   <entry key="connectionTimer">5000</entry>
</properties>

猜你喜欢

转载自shuai121229.iteye.com/blog/2113505