多线程情况下创建连接池
来源:互联网 发布:懒人听书 源码 编辑:程序博客网 时间:2024/06/05 15:25
JAVA数据库连接池实现
博客分类:
• 数据库连接池
JAVA数据库连接池连接池原理连接池实现JAVA连接池
连接池的管理用了了享元模式,这里对连接池进行简单设计。
一、设计思路
1.连接池配置属性DBbean:里面存放可以配置的一些属性
2.连接池接口IConnectionPool:里面定义一些基本的获取连接的一些方法
3.接口实现ConnectionPool:对上面操作进行实现,并加入一些其他方法
4.连接池管理ConnectionPoolManager:管理所有的不同的连接池,所有的连接都能通过这里进行获得连接
5.另外还有几个测试类,和连接信息模拟的类,这里就不进行xml 和配置文件信息的读取了
Java代码
1. package pool; 2. /** 3. * 这是外部可以配置的连接池属性 4. * 可以允许外部配置,拥有默认值 5. * @author Ran 6. * 7. */ 8. public class DBbean { 9. // 连接池属性 10. private String driverName; 11. private String url; 12. private String userName; 13. private String password; 14. // 连接池名字 15. private String poolName; 16. private int minConnections = 1; // 空闲池,最小连接数 17. private int maxConnections = 10; // 空闲池,最大连接数 18. 19. private int initConnections = 5;// 初始化连接数 20. 21. private long connTimeOut = 1000;// 重复获得连接的频率 22. 23. private int maxActiveConnections = 100;// 最大允许的连接数,和数据库对应 24. 25. private long connectionTimeOut = 1000*60*20;// 连接超时时间,默认20分钟 26. 27. private boolean isCurrentConnection = true; // 是否获得当前连接,默认true 28. 29. private boolean isCheakPool = true; // 是否定时检查连接池 30. private long lazyCheck = 1000*60*60;// 延迟多少时间后开始 检查 31. private long periodCheck = 1000*60*60;// 检查频率 32. 33. 34. 35. public DBbean(String driverName, String url, String userName, 36. String password, String poolName) { 37. super(); 38. this.driverName = driverName; 39. this.url = url; 40. this.userName = userName; 41. this.password = password; 42. this.poolName = poolName; 43. } 44. public DBbean() { 45. } 46. public String getDriverName() { 47. if(driverName == null){ 48. driverName = this.getDriverName()+"_"+this.getUrl(); 49. } 50. return driverName; 51. } 52. public void setDriverName(String driverName) { 53. this.driverName = driverName; 54. } 55. public String getUrl() { 56. return url; 57. } 58. public void setUrl(String url) { 59. this.url = url; 60. } 61. public String getUserName() { 62. return userName; 63. } 64. public void setUserName(String userName) { 65. this.userName = userName; 66. } 67. public String getPassword() { 68. return password; 69. } 70. public void setPassword(String password) { 71. this.password = password; 72. } 73. public String getPoolName() { 74. return poolName; 75. } 76. public void setPoolName(String poolName) { 77. this.poolName = poolName; 78. } 79. public int getMinConnections() { 80. return minConnections; 81. } 82. public void setMinConnections(int minConnections) { 83. this.minConnections = minConnections; 84. } 85. public int getMaxConnections() { 86. return maxConnections; 87. } 88. public void setMaxConnections(int maxConnections) { 89. this.maxConnections = maxConnections; 90. } 91. public int getInitConnections() { 92. return initConnections; 93. } 94. public void setInitConnections(int initConnections) { 95. this.initConnections = initConnections; 96. } 97. 98. public int getMaxActiveConnections() { 99. return maxActiveConnections; 100. } 101. public void setMaxActiveConnections(int maxActiveConnections) { 102. this.maxActiveConnections = maxActiveConnections; 103. } 104. public long getConnTimeOut() { 105. return connTimeOut; 106. } 107. public void setConnTimeOut(long connTimeOut) { 108. this.connTimeOut = connTimeOut; 109. } 110. public long getConnectionTimeOut() { 111. return connectionTimeOut; 112. } 113. public void setConnectionTimeOut(long connectionTimeOut) { 114. this.connectionTimeOut = connectionTimeOut; 115. } 116. public boolean isCurrentConnection() { 117. return isCurrentConnection; 118. } 119. public void setCurrentConnection(boolean isCurrentConnection) { 120. this.isCurrentConnection = isCurrentConnection; 121. } 122. public long getLazyCheck() { 123. return lazyCheck; 124. } 125. public void setLazyCheck(long lazyCheck) { 126. this.lazyCheck = lazyCheck; 127. } 128. public long getPeriodCheck() { 129. return periodCheck; 130. } 131. public void setPeriodCheck(long periodCheck) { 132. this.periodCheck = periodCheck; 133. } 134. public boolean isCheakPool() { 135. return isCheakPool; 136. } 137. public void setCheakPool(boolean isCheakPool) { 138. this.isCheakPool = isCheakPool; 139. } 140. 141. 142. 143. }
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
1. package pool; 2. 3. import java.sql.Connection; 4. /** 5. * 模拟线程启动,去获得连接 6. * @author Ran 7. * 8. */ 9. public class ThreadConnection implements Runnable{ 10. private IConnectionPool pool; 11. @Override 12. public void run() { 13. pool = ConnectionPoolManager.getInstance().getPool("testPool"); 14. } 15. 16. public Connection getConnection(){ 17. Connection conn = null; 18. if(pool != null && pool.isActive()){ 19. conn = pool.getConnection(); 20. } 21. return conn; 22. } 23. 24. public Connection getCurrentConnection(){ 25. Connection conn = null; 26. if(pool != null && pool.isActive()){ 27. conn = pool.getCurrentConnecton(); 28. } 29. return conn; 30. } 31. }
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.上面仅仅写了连接池基本原理,关于多线程下连接池的管理没写,后面对多线程操作熟练了添加吧
- 多线程情况下创建连接池
- 多线程情况下的单例模式创建
- 什么情况下使用多线程
- 什么情况下使用多线程?
- 多线程情况下慎用localtime_r
- 什么情况下使用多线程
- 什么情况下使用多线程
- 单例模式:单线程和多线程并发情况下的对象创建
- Linux下创建多线程
- proxool连接池情况下rowset的使用
- proxool连接池情况下rowset的使用
- proxool连接池情况下rowset的使用
- 什么是连接池:Ado.net连接池使用总结:什么情况下需要禁用连接池?
- 谨以此文记录我的ATL COM组件的学习之路--多线程情况下,连接点的使用方法。
- 并发情况下的多线程学习目录
- EclipsePlug-in多线程情况下访问控件
- 什么情况下用多线程编程
- 什么情况下用多线程编程
- 数论-hdu_4548_美素数
- 学习路径规划
- SDUT 3401 数据结构实验之排序四:寻找大富翁 堆排序
- 高效Web开发的10个jQuery代码片段
- 【Android开发0】Android 架构-2016.5.5
- 多线程情况下创建连接池
- linux基础(10)--文件普通权限与特殊权限管理--RHEL6.5
- hdu5668Circle
- python 类中的__nozero__ ,__len__ 重写,可以定义对象的布尔值是True or False
- Eclipse常用快捷键
- HDU 2874Connections between cities LCA
- NSString的常用方法
- Linux内核移植 part1:uboot 框架及移植
- Qt图形库——Qt画图板