多线程情况下创建连接池
JAVA數據庫連接池實現
博客分類:
? 數據庫連接池
JAVA數據庫連接池連接池原理連接池實現JAVA連接池
連接池的管理用了了享元模式,這里對連接池進行簡單設計。
一、設計思路
1.連接池配置屬性DBbean:里面存放可以配置的一些屬性
2.連接池接口IConnectionPool:里面定義一些基本的獲取連接的一些方法
3.接口實現ConnectionPool:對上面操作進行實現,并加入一些其他方法
4.連接池管理ConnectionPoolManager:管理所有的不同的連接池,所有的連接都能通過這里進行獲得連接
5.另外還有幾個測試類,和連接信息模擬的類,這里就不進行xml 和配置文件信息的讀取了
Java代碼
Java代碼
1. package pool; 2. 3. import java.sql.Connection; 4. import java.sql.SQLException; 5. 6. public interface IConnectionPool { 7. // 獲得連接 8. public Connection getConnection(); 9. // 獲得當前連接 10. public Connection getCurrentConnecton(); 11. // 回收連接 12. public void releaseConn(Connection conn) throws SQLException; 13. // 銷毀清空 14. public void destroy(); 15. // 連接池是活動狀態 16. public boolean isActive(); 17. // 定時器,檢查連接池 18. public void cheackPool(); 19. }Java代碼
1. package pool; 2. 3. import java.sql.Connection; 4. import java.sql.DriverManager; 5. import java.sql.SQLException; 6. import java.util.List; 7. import java.util.Timer; 8. import java.util.TimerTask; 9. import java.util.Vector; 10. 11. public class ConnectionPool implements IConnectionPool { 12. // 連接池配置屬性 13. private DBbean dbBean; 14. private boolean isActive = false; // 連接池活動狀態 15. private int contActive = 0;// 記錄創建的總的連接數 16. 17. // 空閑連接 18. private List<Connection> freeConnection = new Vector<Connection>(); 19. // 活動連接 20. private List<Connection> activeConnection = new Vector<Connection>(); 21. // 將線程和連接綁定,保證事務能統一執行 22. private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>(); 23. 24. public ConnectionPool(DBbean dbBean) { 25. super(); 26. this.dbBean = dbBean; 27. init(); 28. cheackPool(); 29. } 30. 31. // 初始化 32. public void init() { 33. try { 34. Class.forName(dbBean.getDriverName()); 35. for (int i = 0; i < dbBean.getInitConnections(); i++) { 36. Connection conn; 37. conn = newConnection(); 38. // 初始化最小連接數 39. if (conn != null) { 40. freeConnection.add(conn); 41. contActive++; 42. } 43. } 44. isActive = true; 45. } catch (ClassNotFoundException e) { 46. e.printStackTrace(); 47. } catch (SQLException e) { 48. e.printStackTrace(); 49. } 50. } 51. 52. // 獲得當前連接 53. public Connection getCurrentConnecton(){ 54. // 默認線程里面取 55. Connection conn = threadLocal.get(); 56. if(!isValid(conn)){ 57. conn = getConnection(); 58. } 59. return conn; 60. } 61. 62. // 獲得連接 63. public synchronized Connection getConnection() { 64. Connection conn = null; 65. try { 66. // 判斷是否超過最大連接數限制 67. if(contActive < this.dbBean.getMaxActiveConnections()){ 68. if (freeConnection.size() > 0) { 69. conn = freeConnection.get(0); 70. if (conn != null) { 71. threadLocal.set(conn); 72. } 73. freeConnection.remove(0); 74. } else { 75. conn = newConnection(); 76. } 77. 78. }else{ 79. // 繼續獲得連接,直到從新獲得連接 80. wait(this.dbBean.getConnTimeOut()); 81. conn = getConnection(); 82. } 83. if (isValid(conn)) { 84. activeConnection.add(conn); 85. contActive ++; 86. } 87. } catch (SQLException e) { 88. e.printStackTrace(); 89. } catch (ClassNotFoundException e) { 90. e.printStackTrace(); 91. } catch (InterruptedException e) { 92. e.printStackTrace(); 93. } 94. return conn; 95. } 96. 97. // 獲得新連接 98. private synchronized Connection newConnection() 99. throws ClassNotFoundException, SQLException { 100. Connection conn = null; 101. if (dbBean != null) { 102. Class.forName(dbBean.getDriverName()); 103. conn = DriverManager.getConnection(dbBean.getUrl(), 104. dbBean.getUserName(), dbBean.getPassword()); 105. } 106. return conn; 107. } 108. 109. // 釋放連接 110. public synchronized void releaseConn(Connection conn) throws SQLException { 111. if (isValid(conn)&& !(freeConnection.size() > dbBean.getMaxConnections())) { 112. freeConnection.add(conn); 113. activeConnection.remove(conn); 114. contActive --; 115. threadLocal.remove(); 116. // 喚醒所有正待等待的線程,去搶連接 117. notifyAll(); 118. } 119. } 120. 121. // 判斷連接是否可用 122. private boolean isValid(Connection conn) { 123. try { 124. if (conn == null || conn.isClosed()) { 125. return false; 126. } 127. } catch (SQLException e) { 128. e.printStackTrace(); 129. } 130. return true; 131. } 132. 133. // 銷毀連接池 134. public synchronized void destroy() { 135. for (Connection conn : freeConnection) { 136. try { 137. if (isValid(conn)) { 138. conn.close(); 139. } 140. } catch (SQLException e) { 141. e.printStackTrace(); 142. } 143. } 144. for (Connection conn : activeConnection) { 145. try { 146. if (isValid(conn)) { 147. conn.close(); 148. } 149. } catch (SQLException e) { 150. e.printStackTrace(); 151. } 152. } 153. isActive = false; 154. contActive = 0; 155. } 156. 157. // 連接池狀態 158. @Override 159. public boolean isActive() { 160. return isActive; 161. } 162. 163. // 定時檢查連接池情況 164. @Override 165. public void cheackPool() { 166. if(dbBean.isCheakPool()){ 167. new Timer().schedule(new TimerTask() { 168. @Override 169. public void run() { 170. // 1.對線程里面的連接狀態 171. // 2.連接池最小 最大連接數 172. // 3.其他狀態進行檢查,因為這里還需要寫幾個線程管理的類,暫時就不添加了 173. System.out.println("空線池連接數:"+freeConnection.size()); 174. System.out.println("活動連接數::"+activeConnection.size()); 175. System.out.println("總的連接數:"+contActive); 176. } 177. },dbBean.getLazyCheck(),dbBean.getPeriodCheck()); 178. } 179. } 180. }Java代碼
1. package pool;
2.
3. import java.sql.Connection;
4. import java.sql.SQLException;
5. import java.util.Hashtable;
6. /**
7. * 連接管理類
8. * @author Ran
9. *
10. */
11. public class ConnectionPoolManager {
12.
13.
14. // 連接池存放
15. public Hashtable
Java代碼
1. package pool; 5. public class Client { 6. public static void main(String[] args) throws InterruptedException { 7. // 初始化連接池 8. Thread t = init(); 9. t.start(); 10. t.join(); 11. 12. ThreadConnection a = new ThreadConnection(); 13. ThreadConnection b = new ThreadConnection(); 14. ThreadConnection c = new ThreadConnection(); 15. Thread t1 = new Thread(a); 16. Thread t2 = new Thread(b); 17. Thread t3 = new Thread(c); 18. 19. 20. // 設置優先級,先讓初始化執行,模擬 線程池 先啟動 21. // 這里僅僅表面控制了,因為即使t 線程先啟動,也不能保證pool 初始化完成,為了簡單模擬,這里先這樣寫了 22. t1.setPriority(10); 23. t2.setPriority(10); 24. t3.setPriority(10); 25. t1.start(); 26. t2.start(); 27. t3.start(); 28. 29. System.out.println("線程A-> "+a.getConnection()); 30. System.out.println("線程B-> "+b.getConnection()); 31. System.out.println("線程C-> "+c.getConnection()); 32. } 33. 34. // 初始化 35. public static Thread init() { 36. Thread t = new Thread(new Runnable() { 37. @Override 38. public void run() { 39. IConnectionPool pool = initPool(); 40. while(pool == null || !pool.isActive()){ 41. pool = initPool(); 42. } 43. } 44. }); 45. return t; 46. } 47. 48. public static IConnectionPool initPool(){ 49. return ConnectionPoolManager.getInstance().getPool("testPool"); 50. } 51. 52. }小結 :
1.連接池誕生原因是,如果每次都從數據庫獲得連接,時間比較長,因此我們提前做建立一些連接,放在連接池里面,每次都從里面取
2.上面僅僅寫了連接池基本原理,關于多線程下連接池的管理沒寫,后面對多線程操作熟練了添加吧
總結
以上是生活随笔為你收集整理的多线程情况下创建连接池的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IO流概览
- 下一篇: Java源文件的编译、下载、解释和执行