ConnectionPool的实现

本连接池使用了代理模式,消除了油漆工那种繁琐的编码方式,本来嘛,只是修改一个close方法何必去实现整个Connection类。其中main函数中的Connection c11 = ConnectionPool.getConnection();将会报错(应为连接数超过了最大连接数),去掉改行本连接池将能正常运行了,由于注释比较详细,在这里就不多废话了,请个位看如下代码。

java 代码
  1. package cc.vicp.eden.plug;   
  2.   
  3. import java.sql.*;   
  4. import java.util.*;   
  5. import java.lang.reflect.*;   
  6.   
  7. /**  
  8.  * 连接池类。  
  9.  *   
  10.  * @version 0.12  
  11.  * @author Eden  
  12.  *   
  13.  */  
  14. public abstract class ConnectionPool {   
  15.     /**  
  16.      * 连接池。  
  17.      */  
  18.     private static final LinkedList<ConnectionHandler> pool;   
  19.   
  20.     /**  
  21.      * 最小连接数量,最大连接数量。  
  22.      */  
  23.     private static final int minConn, maxConn;   
  24.   
  25.     /**  
  26.      * 当前连接数量。  
  27.      */  
  28.     private static int curConn;   
  29.   
  30.     /**  
  31.      * 数据库的基本参数。  
  32.      */  
  33.     private static final String className, url, user, password;   
  34.     /**  
  35.      * 静态初始化。  
  36.      */  
  37.     static {   
  38.         // 初始化池。   
  39.         pool = new LinkedList<ConnectionHandler>();   
  40.         // 初始化基本连接信息。   
  41.         minConn = 3;   
  42.         maxConn = 10;   
  43.         curConn = 0;   
  44.   
  45.         className = "com.mysql.jdbc.Driver";   
  46.         url = "jdbc:mysql://localhost/jforum";   
  47.         user = "root";   
  48.         password = "n8NrCwfj";   
  49.   
  50.         // 加载数据库驱动。   
  51.         try {   
  52.             Class.forName(className);   
  53.         } catch (ClassNotFoundException e) {   
  54.             e.printStackTrace();   
  55.         }   
  56.     }   
  57.   
  58.     /**  
  59.      * 得到一个连接。  
  60.      *   
  61.      * @return 连接(Connection)对象。  
  62.      * @throws SQLException  
  63.      */  
  64.     public static Connection getConnection() throws SQLException {   
  65.         // 当前已经使用的连接是否达到或超出最大连接数?   
  66.         if (curConn >= maxConn)   
  67.             // 抛出连接用尽异常。   
  68.             throw new ConnectExhaustException();   
  69.         Connection conn = null;   
  70.         synchronized (pool) {   
  71.             // 连接池内的连接是否有可用连接?   
  72.             if (pool.size() > 0) {   
  73.                 ConnectionHandler handler = null;   
  74.                 // 得到一个连接管理者,并从连接池中移除。   
  75.                 handler = pool.removeFirst();   
  76.                 // 将该连接管理者设为可用。   
  77.                 handler.enabled = true;   
  78.                 // 创建一个连接管理者(以代理方式创建)。   
  79.                 conn = (Connection) Proxy.newProxyInstance(handler.conn   
  80.                         .getClass().getClassLoader(), handler.conn.getClass()   
  81.                         .getInterfaces(), handler);   
  82.             } else {   
  83.                 // 创建一个链接。   
  84.                 conn = DriverManager.getConnection(url, user, password);   
  85.                 // 创建一个连接管理者(以代理方式创建)。   
  86.                 conn = (Connection) Proxy.newProxyInstance(conn.getClass()   
  87.                         .getClassLoader(), conn.getClass().getInterfaces(),   
  88.                         new ConnectionHandler(conn));   
  89.             }   
  90.             // 当前已使用连接数增加1。   
  91.             curConn++;   
  92.         }   
  93.         // 以连接的方式返回连接管理者对象   
  94.         return conn;   
  95.     }   
  96.   
  97.     /**  
  98.      * 连接管理者类。  
  99.      *   
  100.      * @author Eden  
  101.      *   
  102.      */  
  103.     private static class ConnectionHandler implements InvocationHandler {   
  104.         /**  
  105.          * 连接是否可用。  
  106.          */  
  107.         private boolean enabled;   
  108.   
  109.         /**  
  110.          * 连接(Connection)对象。  
  111.          */  
  112.         private Connection conn;   
  113.   
  114.         /**  
  115.          * 构造器。  
  116.          *   
  117.          * @param conn  
  118.          *            连接(Connection)对象。  
  119.          *   
  120.          */  
  121.         public ConnectionHandler(Connection conn) {   
  122.             this.conn = conn;   
  123.             enabled = true;   
  124.         }   
  125.   
  126.         /**  
  127.          * 代理方法,特别对于close方法进行了处理。  
  128.          */  
  129.         public Object invoke(Object proxy, Method method, Object[] args)   
  130.                 throws Throwable {   
  131.             // 该连接管理者是否不可用?   
  132.             if (!enabled)   
  133.                 // 抛出空指针异常   
  134.                 throw new NullPointerException();   
  135.             synchronized (pool) {   
  136.                 // 是否调用了close方法?   
  137.                 if (method.getName() == "close") {   
  138.                     // 已使用连接数是否超出了最小连接数。   
  139.                     if (curConn > minConn) {   
  140.                         // 关闭连接。   
  141.                         conn.close();   
  142.                     } else {   
  143.                         // 将连接管理者设为不可用。   
  144.                         this.enabled = false;   
  145.                         // 将该连接返回连接池中。   
  146.                         pool.add(this);   
  147.                     }   
  148.                     // 当前已使用连接数减少1。   
  149.                     curConn--;   
  150. System.out.println(Thread.currentThread().getName() + " : " + method.getName() + "\ncurConn:" + curConn + "\npool:" + pool.size() + "\n");   
  151.                     // 返回一个空值。   
  152.                     return null;   
  153.                 }   
  154.             }   
  155.             // 正常调用连接的各种方法。   
  156.             return method.invoke(conn, args);   
  157.         }   
  158.   
  159.     }   
  160.   
  161.     /**  
  162.      * 连接用尽异常类。  
  163.      *   
  164.      * @author Eden  
  165.      *   
  166.      */  
  167.     private static final class ConnectExhaustException extends RuntimeException {   
  168.         /**  
  169.          * 版本序列号。  
  170.          */  
  171.         private static final long serialVersionUID = 0L;   
  172.     }   
  173.   
  174.     public static void main(String[] args) throws SQLException,   
  175.             InterruptedException {   
  176.         for (int i = 0; i < 50; i++) {   
  177.             Connection conn = null;   
  178.             try {   
  179.                 conn = getConnection();   
  180.             } catch (ConnectExhaustException e) {   
  181.                 Thread.sleep(1000);   
  182.                 i--;   
  183.                 continue;   
  184.             }   
  185.             new Monitor(conn, "Monitor - " + i);   
  186.         }   
  187.     }   
  188. }   
  189.   
  190. class Monitor extends Thread {   
  191.   
  192.     private Connection conn;   
  193.   
  194.     public Monitor(Connection conn, String name) {   
  195.         this.conn = conn;   
  196.         this.setName(name);   
  197.         this.start();   
  198.     }   
  199.   
  200.     public void run() {   
  201.         try {   
  202.             Thread.sleep(10000);   
  203.             conn.close();   
  204.         } catch (SQLException e) {   
  205.             e.printStackTrace();   
  206.         } catch (InterruptedException e) {   
  207.             e.printStackTrace();   
  208.         }   
  209.     }   
  210. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值