java 数据库连接池的实现代码

系统 2163 0

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. }  

java 数据库连接池的实现代码


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论