用java实现JDBC数据库连接池

这次写数据库连接池主要想解决的还是servlet访问数据库获取数据的稳定性问题,于是便研究了一下,下面来讲一讲如何用java来写一个适合自己用的数据库连接池。这个东西大家并不陌生,通过使用数据连接池我们能够更好地控制程序和数据库之间建立的连接,减小数据库访问压力,也便于管理连接,提高了利用率和工作性能。

  设计数据库连接池,个人认为应该注意以下几点:

  1、能够控制连接池的大小

  2、有一个统一的接口用于获得连接

  3、使用后的连接要有一个接口能够接受并处理掉

  4、连接池要有自我维护能力,比如说暂时提高连接池大小以应对可能的连接小高潮,或者处理多余的连接

 

  ok,我们先确定连接池的数据结构:

复制代码
 1 public class SimpleConnetionPool {
 2     private static LinkedList m_notUsedConnection = new LinkedList();
 3     private static HashSet m_usedUsedConnection = new HashSet();
 4     private static String m_url = "";
 5     private static String m_user = "";
 6     private static String m_password = "";
 7     private static int m_maxConnect = 3;
 8     static final boolean DEBUG = false;
 9     static private long m_lastClearClosedConnection = System
10             .currentTimeMillis();
11     public static long CHECK_CLOSED_CONNECTION_TIME = 5000; // 5秒
12 }
复制代码

  

  然后我们看看数据库连接池的核心部分,首先是清除连接池中多余的连接。我们每隔一段时间就对连接池中的所有连接进行检查,第一轮循环判断这些链接是否已经关闭,如果关闭了则直接移除它们,第二轮循环则是根据目前规定的最大数量裁撤空闲连接。

复制代码
 1 private static void clearClosedConnection() {
 2         long time = System.currentTimeMillis();
 3 
 4         // 时间不合理,没有必要检查
 5         if (time < m_lastClearClosedConnection) {
 6             time = m_lastClearClosedConnection;
 7             return;
 8         }
 9 
10         // 时间太短,没有必要检查
11         if (time - m_lastClearClosedConnection < CHECK_CLOSED_CONNECTION_TIME) {
12             return;
13         }
14 
15         m_lastClearClosedConnection = time;
16 
17         // 开始检查没有使用的Connection
18         Iterator iterator = m_notUsedConnection.iterator();
19         while (iterator.hasNext()) {
20             Connection con = (Connection) iterator.next();
21 
22             try {
23                 if (con.isClosed()) {
24                     iterator.remove();
25                 }
26             } catch (SQLException e) {
27                 iterator.remove();
28 
29                 if (DEBUG) {
30                     System.out.println("问题连接已断开");
31                 }
32             }
33         }
34 
35         // 清除多余的Connection
36         int decrease = getDecreasingConnectionCount();
37 
38         while (decrease > 0 && m_notUsedConnection.size() > 0) {
39             Connection con = (Connection) m_notUsedConnection.removeFirst();
40 
41             try {
42                 con.close();
43             } catch (SQLException e) {
44 
45             }
46 
47             decrease--;
48         }
49     }
复制代码

  

  接下来我们看一下申请一个新的连接是如何进行的,首先我们先调用之前的清理器来清除多余的连接和无法使用的连接,之后在空闲连接中寻找是否有可是的连接,如果有符合的则直接分配出去,但是要是没找到的话该怎么办呢?

  这时候我们就需要建立新的连接来提供了,建立新的连接后我们将其中一个分配出去,剩下的加入到空闲连接中去等待分配就可以了。

复制代码
 1 public static synchronized Connection getConnection() {
 2         // 关闭清除多余的连接
 3         clearClosedConnection();
 4 
 5         // 输出当前总连接数
 6         if(DEBUG)
 7             System.out.println("当前总连接数:" + getConnectionCount());
 8 
 9         // 寻找空闲的连接
10         while (m_notUsedConnection.size() > 0) {
11             try {
12                 Connection con = (Connection) m_notUsedConnection.removeFirst();
13 
14                 if (con.isClosed()) {
15                     continue;
16                 }
17 
18                 m_usedUsedConnection.add(con);
19                 if (DEBUG) {
20                     // System.out.println("连接初始化成功");
21                 }
22                 return con;
23             } catch (SQLException e) {
24             }
25         }
26 
27         // 没有找到,建立一些新的连接以供使用
28         int newCount = getIncreasingConnectionCount();
29         LinkedList list = new LinkedList();
30         Connection con = null;
31 
32         for (int i = 0; i < newCount; i++) {
33             con = getNewConnection();
34             if (con != null) {
35                 list.add(con);
36             }
37         }
38 
39         // 没有成功建立连接,访问失败
40         if (list.size() == 0)
41             return null;
42 
43         // 成功建立连接,使用的加入used队列,剩下的加入notUsed队列
44         con = (Connection) list.removeFirst();
45         m_usedUsedConnection.add(con);
46         m_notUsedConnection.addAll(list);
47         list.clear();
48 
49         return con;
50     }
复制代码

  根据之前总结的我们还需要一个,就是交还连接了,这个很简单,把占用中的链接移出来放到空闲连接里就可以了~很简单吧~

复制代码
1 static synchronized void pushConnectionBackToPool(Connection con) {
2         boolean exist = m_usedUsedConnection.remove(con);
3         if (exist) {
4             m_notUsedConnection.addLast(con);
5         }
6     }
复制代码

  

  这就是这个数据连接池的核心部分了,现在我们来看整套代码就容易多了,其实需要注意的就是刚才说的那些:

复制代码
  1 package cn.com.css.cas.jdbc;
  2 
  3 import java.sql.Connection;
  4 import java.sql.Driver;
  5 import java.sql.DriverManager;
  6 import java.sql.SQLException;
  7 import java.util.HashSet;
  8 import java.util.Iterator;
  9 import java.util.LinkedList;
 10 
 11 /**
 12  * JDBC数据库连接池
 13  * 
 14  * @author Woud
 15  * 
 16  */
 17 public class SimpleConnetionPool {
 18     private static LinkedList m_notUsedConnection = new LinkedList();
 19     private static HashSet m_usedUsedConnection = new HashSet();
 20     private static String m_url = "";
 21     private static String m_user = "";
 22     private static String m_password = "";
 23     private static int m_maxConnect = 3;
 24     static final boolean DEBUG = false;
 25     static private long m_lastClearClosedConnection = System
 26             .currentTimeMillis();
 27     public static long CHECK_CLOSED_CONNECTION_TIME = 5000; // 5秒
 28 
 29     static {
 30         try {
 31             initDriver();
 32         } catch (InstantiationException e) {
 33             // TODO Auto-generated catch block
 34             e.printStackTrace();
 35         } catch (IllegalAccessException e) {
 36             // TODO Auto-generated catch block
 37             e.printStackTrace();
 38         } catch (ClassNotFoundException e) {
 39             // TODO Auto-generated catch block
 40             e.printStackTrace();
 41         }
 42     }
 43 
 44     public SimpleConnetionPool(String url, String user, String password) {
 45         m_url = url;
 46         m_user = user;
 47         m_password = password;
 48     }
 49 
 50     private static void initDriver() throws InstantiationException,
 51             IllegalAccessException, ClassNotFoundException {
 52         Driver driver = null;
 53 
 54         // 读取MySql的Driver
 55         driver = (Driver) Class.forName("com.mysql.jdbc.Driver").newInstance();
 56         installDriver(driver);
 57 
 58         /*
 59          * // 读取postgresql的driver driver = (Driver)
 60          * Class.forName("org.postgresql.Driver").newInstance();
 61          * installDriver(driver);
 62          */
 63 
 64     }
 65 
 66     public static void installDriver(Driver driver) {
 67         try {
 68             DriverManager.registerDriver(driver);
 69         } catch (SQLException e) {
 70             // TODO Auto-generated catch block
 71             e.printStackTrace();
 72         }
 73     }
 74 
 75     public static synchronized Connection getConnection() {
 76         // 关闭清除多余的连接
 77         clearClosedConnection();
 78 
 79         // 输出当前总连接数
 80         if(DEBUG)
 81             System.out.println("当前总连接数:" + getConnectionCount());
 82 
 83         // 寻找空闲的连接
 84         while (m_notUsedConnection.size() > 0) {
 85             try {
 86                 Connection con = (Connection) m_notUsedConnection.removeFirst();
 87 
 88                 if (con.isClosed()) {
 89                     continue;
 90                 }
 91 
 92                 m_usedUsedConnection.add(con);
 93                 if (DEBUG) {
 94                     // System.out.println("连接初始化成功");
 95                 }
 96                 return con;
 97             } catch (SQLException e) {
 98             }
 99         }
100 
101         // 没有找到,建立一些新的连接以供使用
102         int newCount = getIncreasingConnectionCount();
103         LinkedList list = new LinkedList();
104         Connection con = null;
105 
106         for (int i = 0; i < newCount; i++) {
107             con = getNewConnection();
108             if (con != null) {
109                 list.add(con);
110             }
111         }
112 
113         // 没有成功建立连接,访问失败
114         if (list.size() == 0)
115             return null;
116 
117         // 成功建立连接,使用的加入used队列,剩下的加入notUsed队列
118         con = (Connection) list.removeFirst();
119         m_usedUsedConnection.add(con);
120         m_notUsedConnection.addAll(list);
121         list.clear();
122 
123         return con;
124     }
125 
126     public static Connection getNewConnection() {
127         try {
128             Connection con = DriverManager.getConnection(m_url, m_user,
129                     m_password);
130             return con;
131         } catch (SQLException e) {
132             // TODO Auto-generated catch block
133             e.printStackTrace();
134         }
135 
136         return null;
137     }
138 
139     static synchronized void pushConnectionBackToPool(Connection con) {
140         boolean exist = m_usedUsedConnection.remove(con);
141         if (exist) {
142             m_notUsedConnection.addLast(con);
143         }
144     }
145 
146     public static int close() {
147         int count = 0;
148 
149         Iterator iterator = m_notUsedConnection.iterator();
150         while (iterator.hasNext()) {
151             try {
152                 ((Connection) iterator.next()).close();
153                 count++;
154             } catch (SQLException e) {
155                 // TODO Auto-generated catch block
156                 e.printStackTrace();
157             }
158         }
159         m_notUsedConnection.clear();
160 
161         iterator = m_usedUsedConnection.iterator();
162         while (iterator.hasNext()) {
163             try {
164                 ((Connection) iterator.next()).close();
165             } catch (SQLException e) {
166                 // TODO Auto-generated catch block
167                 e.printStackTrace();
168             }
169         }
170         m_usedUsedConnection.clear();
171 
172         return count;
173     }
174 
175     private static void clearClosedConnection() {
176         long time = System.currentTimeMillis();
177 
178         // 时间不合理,没有必要检查
179         if (time < m_lastClearClosedConnection) {
180             time = m_lastClearClosedConnection;
181             return;
182         }
183 
184         // 时间太短,没有必要检查
185         if (time - m_lastClearClosedConnection < CHECK_CLOSED_CONNECTION_TIME) {
186             return;
187         }
188 
189         m_lastClearClosedConnection = time;
190 
191         // 开始检查没有使用的Connection
192         Iterator iterator = m_notUsedConnection.iterator();
193         while (iterator.hasNext()) {
194             Connection con = (Connection) iterator.next();
195 
196             try {
197                 if (con.isClosed()) {
198                     iterator.remove();
199                 }
200             } catch (SQLException e) {
201                 iterator.remove();
202 
203                 if (DEBUG) {
204                     System.out.println("问题连接已断开");
205                 }
206             }
207         }
208 
209         // 清除多余的Connection
210         int decrease = getDecreasingConnectionCount();
211 
212         while (decrease > 0 && m_notUsedConnection.size() > 0) {
213             Connection con = (Connection) m_notUsedConnection.removeFirst();
214 
215             try {
216                 con.close();
217             } catch (SQLException e) {
218 
219             }
220 
221             decrease--;
222         }
223     }
224 
225     public static int getIncreasingConnectionCount() {
226         int count = 1;
227         count = getConnectionCount() / 4;
228 
229         if (count < 1)
230             count = 1;
231 
232         return count;
233     }
234 
235     public static int getDecreasingConnectionCount() {
236         int count = 0;
237 
238         if (getConnectionCount() > m_maxConnect) {
239             count = getConnectionCount() - m_maxConnect;
240         }
241 
242         return count;
243     }
244 
245     public static synchronized int getNotUsedConnectionCount() {
246         return m_notUsedConnection.size();
247     }
248 
249     public static synchronized int getUsedConnectionCount() {
250         return m_usedUsedConnection.size();
251     }
252 
253     public static synchronized int getConnectionCount() {
254         return m_notUsedConnection.size() + m_usedUsedConnection.size();
255     }
256 
257 }
复制代码

 

 我们做好了这个连接池之后怎么用呢,这很简单,我们用Singleton模式做一个连接池管理器,然后对接口进行简单的封装后就可以进行使用了,管理器调用连接池的getconnection接口获得connect后和数据库建立连接,运行sql后交还connect并把结果反馈回来就可以了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值