Chinaunix首页 | 论坛 | 博客
  • 博客访问: 78710
  • 博文数量: 8
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 599
  • 用 户 组: 普通用户
  • 注册时间: 2013-06-27 16:46
个人简介

哎……马上就要毕业了!求工作啊^0^

文章分类

全部博文(8)

文章存档

2013年(8)

我的朋友

分类: Java

2013-08-19 23:07:27

1.数据库连接池原理:

2.自定义一个普通数据库连接池的实现:

     属性:连接数据库的相关属性-Driver,url,name,password
              连接池的相关参数-init(初始化连接池个数),max(连接池最大连接数),current(当前连接数)
              List(连接池)
     方法:getConnection(返回池子中的连接)
              releaseConnection(将连接放回到池子)
     首先建立一个库dbutils,和一个test表
    
     代码实现:

点击(此处)折叠或打开

  1. public class DBPool {
  2.     // 定义连接数据库的参数

  3.     String driverclass = "com.mysql.jdbc.Driver";
  4.     String url = "jdbc:mysql:///dbutils";
  5.     String name = "root";
  6.     String psw = "root";
  7.     // 定义存储连接的集合

  8.     public LinkedList<Connection> pool = new LinkedList<Connection>();
  9.     // 定义池子相关的变量

  10.     int init_connection_count = 5;
  11.     int max_connection_count = 10;
  12.     int currrent_connection_count = 0;
  13.     // 定义构造函数进行初始化容量的设置

  14.     public DBPool() {
  15.         try {
  16.             for (int i = 0; i < init_connection_count; i++) {
  17.                 Connection conn = creatConnection();
  18.                 pool.add(conn);
  19.                 currrent_connection_count++;
  20.             }
  21.         } catch (Exception e) {
  22.             System.out.println(e.getMessage());
  23.             System.out.println("初始化连接池失败");
  24.             throw new RuntimeException("初始化连接池失败");
  25.         }
  26.     }
  27.     private Connection creatConnection() throws Exception {
  28.         // 加载驱动

  29.         Class.forName(driverclass);
  30.         // 获取连接

  31.         Connection conn = DriverManager.getConnection(url, name, psw);
  32.         return conn;
  33.     }
  34.     // 提供一个public的返回池子连接的方法


  35.     public Connection getConnection() throws Exception {
  36.         // 判断池子中是否有连接

  37.         if (pool.size() > 0) {
  38.             return this.pool.removeFirst();
  39.         }
  40.         // 判断是否到达池子的最大容量

  41.         if (currrent_connection_count < max_connection_count) {
  42.             currrent_connection_count++;
  43.             return creatConnection();
  44.         }
  45.         // 池子到了最大的容量

  46.         throw new RuntimeException("池子到了最大容量了");
  47.     }
  48.     // 提供一个释放连接的方法

  49.     public void releaseConnection(Connection conn) {
  50.         try {
  51.             if (pool.size() < max_connection_count) {
  52.                 this.pool.addLast(conn);
  53.             } else {
  54.                 // 超过的连接关闭

  55.                 conn.close();
  56.             }
  57.         } catch (Exception e) {
  58.             System.out.println(e.getMessage());
  59.             System.out.println("释放连接失败");
  60.             throw new RuntimeException("释放连接失败");
  61.         }
  62.     }

  63.     public static void main(String[] args) throws Exception {
  64.         DBPool pool = new DBPool();
  65.         System.out.println(pool.pool.size()); //5

  66.         Connection conn = pool.getConnection();
  67.         System.out.println(pool.pool.size()); //4


  68.         String SQL = "insert into test(name) values(?)";
  69.         PreparedStatement state = conn.prepareStatement(SQL);
  70.         state.setString(1, "scoield");
  71.         state.executeUpdate();
  72.         pool.releaseConnection(conn);
  73.         System.out.println(pool.pool.size()); //5

  74.     }
  75. }
-------------------------------------------------------------------------------上面的代码会产生两个问题---------------------------------------------------------------------------------------

1.如果将获取到的Connection关闭,在释放连接,就没有意义了

解决方案:使用代理方式,拦截Connection的close方法
creatConnection()方法代码改进:

点击(此处)折叠或打开

  1. private Connection creatConnection() throws Exception {
  2.         // 加载驱动

  3.         Class.forName(driverclass);
  4.         // 获取连接

  5.         final Connection conn = DriverManager.getConnection(url, name, psw);
  6.         Connection proxy = (Connection)Proxy.newProxyInstance(
  7.                 conn.getClass().getClassLoader(),
  8.                 new Class[]{Connection.class},
  9.                 new InvocationHandler() {
  10.                     Object obj = null;
  11.                     public Object invoke(Object proxy, Method method, Object[] params)
  12.                             throws Throwable {
  13.                         // 判断用户是否调用close方法

  14.                         if ("close".equals(method.getName())) {
  15.                             DBPool.this.releaseConnection(conn);
  16.                             System.out.println("被代理对象拦截并重写了close方法");
  17.                         }else {
  18.                             obj = method.invoke(conn, params);
  19.                         }
  20.                         return obj;
  21.                     }
  22.                 });
  23.         return proxy;
  24.     }

2.线程安全问题

解决方案:加锁
代码优化:

点击(此处)折叠或打开

  1. public Connection getConnection()throws Exception{
  2.         // 同步连接池

  3.         synchronized (this.pool) {
  4.             // 判断池子中是否有连接

  5.             if(this.pool.size() > 0){
  6.                 return this.pool.removeFirst();
  7.             }
  8.             // 判断是否到达池子的最大容量

  9.             if(this.current_connection_count < this.max_connection_count){
  10.                 this.current_connection_count++;
  11.                 return createConnection();
  12.             }
  13.         }
  14.         // 池子到了最大的容量

  15.         throw new Exception("池子到了最大的容量了!");
  16.     }

阅读(2779) | 评论(0) | 转发(0) |
0

上一篇:交换类排序

下一篇:常见的数据库连接池

给主人留下些什么吧!~~