java 数据可连接池的使用。

1.package com.xiaobian;   
2.
3./**
4. * 数据库连接池管理类
5. */
6.import java.io.*;
7.import java.sql.*;
8.import java.util.*;
9.import java.util.Date;
10.
11./**
12. * 管理类DBConnectionManager支持对一个或多个由属性文件定义的数据库连接池的
13. * 访问.客户程序可以调用getInstance()方法访问本类的唯一实例
14. */
15.public class DBConnectionManager {
16.
17. public static void main(String[] args) {
18. DBConnectionManager connectionManager = DBConnectionManager.getInstance();
19.
20. Connection conn = connectionManager.getConnection("idb");
21. try {
22. Thread.sleep(10);
23. } catch (InterruptedException e) {
24. // TODO Auto-generated catch block
25. e.printStackTrace();
26. }
27. Connection conn1 = connectionManager.getConnection("idb");
28. Connection conn2 = connectionManager.getConnection("idb");
29. Connection conn3 = connectionManager.getConnection("idb");
30. Connection conn4 = connectionManager.getConnection("idb");
31. Connection conn5 = connectionManager.getConnection("idb");
32. connectionManager.freeConnection("idb", conn);
33. connectionManager.freeConnection("idb", conn1);
34. connectionManager.freeConnection("idb", conn2);
35. connectionManager.freeConnection("idb", conn3);
36. connectionManager.freeConnection("idb", conn4);
37. connectionManager.freeConnection("idb", conn5);
38. Connection conn6 = connectionManager.getConnection("idb");
39. Connection conn7 = connectionManager.getConnection("idb");
40. System.out.println(" conn6 == "+conn6 +" conn7 == "+conn7);
41.
42. }
43.
44.
45. static private DBConnectionManager instance; // 唯一实例
46.
47. static private int clients; //
48.
49. private Vector drivers = new Vector();
50.
51. private PrintWriter log;
52.
53. private Hashtable pools = new Hashtable();
54.
55. /**
56. * 返回唯一实例.如果是第一次调用此方法,则创建实例
57. *
58. * @return DBConnectionManager 唯一实例
59. */
60. static synchronized public DBConnectionManager getInstance() {
61. if (instance == null) {
62. instance = new DBConnectionManager();
63. }
64. clients++;
65. return instance;
66. }
67.
68. /**
69. * 建构私有函数以防止其它对象创建本类实例
70. */
71. private DBConnectionManager() {
72. init();
73. }
74.
75. /**
76. * 将连接对象返回给由名字指定的连接池
77. *
78. * @param name
79. * 在属性文件中定义的连接池名字
80. * @param con
81. * 连接对象
82. */
83. public void freeConnection(String name, Connection con) {
84. DBConnectionPool pool = (DBConnectionPool) pools.get(name);
85. if (pool != null) {
86. pool.freeConnection(con);
87. }
88. }
89.
90. /**
91. * 获得一个可用的(空闲的)连接.如果没有可用连接,且已有连接数小于最大连接数 限制,则创建并返回新连接
92. *
93. * @param name
94. * 在属性文件中定义的连接池名字
95. * @return Connection 可用连接或null
96. */
97. public Connection getConnection(String name) {
98. DBConnectionPool pool = (DBConnectionPool) pools.get(name);
99. //System.out.println(" pool == "+pool);
100. if (pool != null) {
101. return pool.getConnection();
102. }
103. return null;
104. }
105.
106. /**
107. * 获得一个可用连接.若没有可用连接,且已有连接数小于最大连接数限制, 则创建并返回新连接.否则,在指定的时间内等待其它线程释放连接.
108. *
109. * @param name
110. * 连接池名字
111. * @param time
112. * 以毫秒计的等待时间
113. * @return Connection 可用连接或null
114. */
115. public Connection getConnection(String name, long time) {
116. DBConnectionPool pool = (DBConnectionPool) pools.get(name);
117. if (pool != null) {
118. return pool.getConnection(time);
119. }
120. return null;
121. }
122.
123. /**
124. * 关闭所有连接,撤销驱动程序的注册
125. */
126. public synchronized void release() {
127. // 等待直到最后一个客户程序调用
128. if (--clients != 0) {
129. return;
130. }
131. Enumeration allPools = pools.elements();
132. while (allPools.hasMoreElements()) {
133. DBConnectionPool pool = (DBConnectionPool) allPools.nextElement();
134. pool.release();
135. }
136. Enumeration allDrivers = drivers.elements();
137. while (allDrivers.hasMoreElements()) {
138. Driver driver = (Driver) allDrivers.nextElement();
139. try {
140. DriverManager.deregisterDriver(driver);
141. log("撤销JDBC驱动程序 " + driver.getClass().getName() + "的注册");
142. } catch (SQLException e) {
143. log(e, "无法撤销下列JDBC驱动程序的注册: " + driver.getClass().getName());
144. }
145. }
146. }
147.
148. /**
149. * 根据指定属性创建连接池实例.
150. *
151. * @param props
152. * 连接池属性
153. */
154. private void createPools(Properties props) {
155. Enumeration propNames = props.propertyNames();
156. while (propNames.hasMoreElements()) {
157. String name = (String) propNames.nextElement();
158. if (name.endsWith(".url")) {
159. String poolName = name.substring(0, name.lastIndexOf("."));
160. //System.out.println(" poolName ||"+poolName+"|");
161. String url = props.getProperty(poolName + ".url");
162. if (url == null) {
163. log("没有为连接池" + poolName + "指定URL");
164. continue;
165. }
166. String user = props.getProperty(poolName + ".user");
167. String password = props.getProperty(poolName + ".password");
168. String maxconn = props.getProperty(poolName + ".maxconn", "0");
169. int max;
170. try {
171. max = Integer.valueOf(maxconn).intValue();
172. } catch (NumberFormatException e) {
173. log("错误的最大连接数限制: " + maxconn + " .连接池: " + poolName);
174. max = 0;
175. }
176. DBConnectionPool pool = new DBConnectionPool(poolName, url,
177. user, password, max);
178. pools.put(poolName, pool);
179. log("成功创建连接池" + poolName);
180. }
181. }
182. }
183.
184. // --------------------------------------------------------------------------------
185.
186. /**
187. * 读取属性完成初始化
188. */
189. private void init() {
190.
191. InputStream fileinputstream = null;
192. try {
193. fileinputstream = new FileInputStream("./src/db.properties");
194. } catch (FileNotFoundException e1) {
195. e1.printStackTrace();
196. }
197. //BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(fileinputstream));
198.
199. //InputStream is = getClass().getResourceAsStream("D:/workspace/UmessageSms/src/db.properties");
200. Properties dbProps = new Properties();
201. try {
202. dbProps.load(fileinputstream);
203. } catch (Exception e) {
204. e.printStackTrace();
205. System.err.println("不能读取属性文件. "
206. + "请确保db.properties在CLASSPATH指定的路径中");
207. return;
208. }
209. String logFile = dbProps.getProperty("logfile",
210. "DBConnectionManager.log");
211.
212. //System.out.println(dbProps.getProperty("logfile"));
213. try {
214. log = new PrintWriter(new FileWriter(logFile, true), true);
215. } catch (IOException e) {
216. System.err.println("无法打开日志文件: " + logFile);
217. log = new PrintWriter(System.err);
218. }
219. loadDrivers(dbProps);
220. createPools(dbProps);
221. }
222.
223. /**
224. * 装载和注册所有JDBC驱动程序
225. *
226. * @param props
227. * 属性
228. */
229. private void loadDrivers(Properties props) {
230. String driverClasses = props.getProperty("drivers");
231. StringTokenizer st = new StringTokenizer(driverClasses);
232. while (st.hasMoreElements()) {
233. String driverClassName = st.nextToken().trim();
234. try {
235. Driver driver = (Driver) Class.forName(driverClassName)
236. .newInstance();
237. DriverManager.registerDriver(driver);
238. drivers.addElement(driver);
239. log("成功注册JDBC驱动程序" + driverClassName);
240. } catch (Exception e) {
241. log("无法注册JDBC驱动程序: " + driverClassName + ", 错误: " + e);
242. }
243. }
244. }
245.
246. /**
247. * 将文本信息写入日志文件
248. */
249. private void log(String msg) {
250. log.println(new Date() + ": " + msg);
251. }
252.
253. /**
254. * 将文本信息与异常写入日志文件
255. */
256. private void log(Throwable e, String msg) {
257. log.println(new Date() + ": " + msg);
258. e.printStackTrace(log);
259. }
260.
261. /** ************************************************************* */
262. /** ********************内部类DBConnectionPool******************** */
263. /** ************************************************************* */
264. /**
265. * 此内部类定义了一个连接池.它能够根据要求创建新连接,直到预定的最 大连接数为止.在返回连接给客户程序之前,它能够验证连接的有效性.
266. */
267. class DBConnectionPool {
268. private int checkedOut; // 当前连接数
269.
270. private Vector freeConnections = new Vector(); // 保存所有可用连接
271.
272. private int maxConn; // 此连接池允许建立的最大连接数
273.
274. private String name; // 连接池名字
275.
276. private String password; // 密码或null
277.
278. private String URL; // 数据库的JDBC URL
279.
280. private String user; // 数据库账号或null
281.
282. /**
283. * 创建新的连接池
284. *
285. * @param name
286. * 连接池名字
287. * @param URL
288. * 数据库的JDBC URL
289. * @param user
290. * 数据库帐号或 null
291. * @param password
292. * 密码或 null
293. * @param maxConn
294. * 此连接池允许建立的最大连接数
295. */
296. public DBConnectionPool(String name, String URL, String user,
297. String password, int maxConn) {
298. this.name = name;
299. this.URL = URL;
300. this.user = user;
301. this.password = password;
302. this.maxConn = maxConn;
303. }
304.
305. /**
306. * 将不再使用的连接返回给连接池
307. *
308. * @param con
309. * 客户程序释放的连接
310. */
311. public synchronized void freeConnection(Connection con) {
312. // 将指定连接加入到向量末尾
313. freeConnections.addElement(con);
314. checkedOut--;
315. notifyAll(); // 删除等待队列中的所有线程
316. }
317.
318. /**
319. * 从连接池获得一个可用连接.如果没有空闲的连接且当前连接数小于最大连接
320. * 数限制,则创建新连接.如原来登记为可用的连接不再有效,则从向量删除之, 然后递归调用自己以尝试新的可用连接.
321. */
322. public synchronized Connection getConnection() {
323. Connection con = null;
324. //System.out.println(" freeConnections.size() "+freeConnections.size());
325. if (freeConnections.size() > 0) {
326. // 获取向量中第一个可用连接
327. con = (Connection) freeConnections.firstElement();
328. freeConnections.removeElementAt(0);
329. try {
330. if (con.isClosed()) {
331. log("从连接池" + name + "删除一个无效连接");
332. // 递归调用自己,尝试再次获取可用连接
333. con = getConnection();
334. }
335. } catch (SQLException e) {
336. log("从连接池" + name + "删除一个无效连接");
337. // 递归调用自己,尝试再次获取可用连接
338. con = getConnection();
339. }
340. } else if (maxConn == 0 || checkedOut < maxConn) {
341. con = newConnection();
342. }
343. if (con != null) {
344. checkedOut++;
345. }
346. System.out.println("con == "+con);
347. return con;
348. }
349.
350. /**
351. * 从连接池获取可用连接.可以指定客户程序能够等待的最长时间 参见前一个getConnection()方法.
352. *
353. * @param timeout
354. * 以毫秒计的等待时间限制
355. */
356. public synchronized Connection getConnection(long timeout) {
357. long startTime = new Date().getTime();
358. Connection con;
359. while ((con = getConnection()) == null) {
360. try {
361. wait(timeout);
362. } catch (InterruptedException e) {
363. }
364. if ((new Date().getTime() - startTime) >= timeout) {
365. // wait()返回的原因是超时
366. return null;
367. }
368. }
369. return con;
370. }
371.
372. /**
373. * 关闭所有连接
374. */
375. public synchronized void release() {
376. Enumeration allConnections = freeConnections.elements();
377. while (allConnections.hasMoreElements()) {
378. Connection con = (Connection) allConnections.nextElement();
379. try {
380. con.close();
381. log("关闭连接池" + name + "中的一个连接");
382. } catch (SQLException e) {
383. log(e, "无法关闭连接池" + name + "中的连接");
384. }
385. }
386. freeConnections.removeAllElements();
387. }
388.
389. /**
390. * 创建新的连接
391. */
392. private Connection newConnection() {
393. Connection con = null;
394. try {
395. if (user == null) {
396. con = DriverManager.getConnection(URL);
397. } else {
398. con = DriverManager.getConnection(URL, user, password);
399. }
400. log("连接池" + name + "创建一个新的连接");
401. } catch (SQLException e) {
402. log(e, "无法创建下列URL的连接: " + URL);
403. return null;
404. }
405. return con;
406. }
407. }
408.}



转载自:http://xiaobian.iteye.com/blog/111797
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值