现在的位置: 首页 > 综合 > 正文

java 数据库连接池

2012年09月16日 ⁄ 综合 ⁄ 共 14308字 ⁄ 字号 评论关闭

数据库连接池,是一种相当实用的应用程序。它可以保存、维护及创建用户所需的数据库连接。从而使得用户得到一个连接的时间降低90%以上。大大提升了数据库访问的反应时间。

 

这个是一个开源的代码。大家可以修改它、使用它。

 

希望我的代码能对大家有用。

 

此代码,经过1000数量级的多线程并发访问测试。在四核CPU下也进行了多线程测试。保证了连接池在真多线程上同步访问的安全性。

里面包含了一个公开的接口。使用这个接口里面的函数。可以轻易创建使用数据库连接池服务。

使用一个守护线程维护这个连接池,完全自动化。

 

下载连接:http://download.csdn.net/user/lauo1188

 

 

连接池接口类:

 

  1. package mysql;  
  2. import java.sql.*;  
  3. import java.sql.ResultSet;  
  4. public interface Pool  
  5. {  
  6.     public boolean start(String dbname,String user,String psw);  //启动数据库连接池服务  
  7.     //以下start函数将允许用户设置最低空闲连接数,最高空闲连接数,最大连接数  
  8.     public boolean start(int lows,int maxs,int maxc,String dbname,String user,String psw);  
  9.     public Connection getConnection();  //得到连接器  
  10.     public boolean freeConnection(Connection con);//将连接返回到连接池中  
  11.     public boolean close(); //清除连接池,并且关闭它(使之变得不可用)  
  12. }  

 

 

 

第一个实现类:VectorPool

 

 

  1. /** 
  2.  * @(#)Pool.java 
  3.  * 
  4.  * 
  5.  * @author  lauo 
  6.  * @version 1.00 2010/5/15 
  7.  * 
  8.  * 测试完成于2010-5-16  22:40分 
  9.  */  
  10. package mysql;  
  11. import mysql.*;  
  12. import java.sql.*;  
  13. import java.util.*;  
  14. /* 
  15.  *这里将实现ConnectionPool接口 
  16.  */  
  17. public class VectorPool extends Thread implements Pool   
  18. {  
  19.     protected final boolean debug = false//是否debug态(如是  输出debug状态信息)  
  20.     protected boolean init = false;//是否已经将setting初始化  
  21.     //timeDiff   一个连接超过此时间未使用过,则需要更新此连接----1小时  
  22.     protected final long timeDiff =  60*60*1000 ;//1小时60分钟,1分钟60秒,1秒1000毫秒  
  23.     protected int lows = 20 ; //连接池的最小空闲连接数  
  24.     protected int maxs = 100 ; //连接池的最大空闲连接数  
  25.     protected int maxc = 100;  
  26.     protected String dbname = null;  
  27.     protected String user = null;  
  28.     protected String psw = null;  
  29.       
  30.     protected Integer conCount = 0//这个是静态的。当前连接数  
  31.     //下面是连接保存的池  
  32.     protected Vector<ConInfo> pool = new Vector<ConInfo>();  
  33.     public VectorPool()   
  34.     {  
  35.     }  
  36.     public void start()  
  37.     {  
  38.           
  39.     }  
  40.     //得到当前连接数  
  41.     protected int getConCount()  
  42.     {  
  43.         return conCount;  
  44.     }  
  45.     /* 
  46.      *设置数据库连接的基本参数 
  47.      */  
  48.     public  synchronized  boolean start(String db,String u,String p)  
  49.     {  
  50.         if(false == init && null != pool)//如果未初始化,且连接池可用  
  51.         {  
  52.             dbname  =   db;  
  53.             user    =   u;  
  54.             psw     =   p;  
  55.             if(test())  
  56.             {  
  57.                 init    =   true;  
  58.                 super.start();   
  59.                 return true;  
  60.             }  
  61.             else return false;  
  62.         }  
  63.         else  
  64.             return false;  
  65.     }  
  66.     public synchronized boolean start(int l,int m,int mc,String db,String u,String p)  
  67.     {  
  68.         if(l<0 || m<0 ||l>=m || m>mc)//0<l<m<=mc  
  69.             return false;  
  70.         if(false == init && null != pool)//如果未初始化,且连接池可用  
  71.         {  
  72.             dbname  =   db;  
  73.             user    =   u;  
  74.             psw     =   p;  
  75.             if(test())  
  76.             {  
  77.                 init    =   true;  
  78.                 lows = l<5?5:l;  //这里允许的最小的值为5  
  79.                 maxs = m<10?10:m; //这里允许的最小的值为10  
  80.                 maxc = mc<20 ?20:mc;//这里允许的连接数  
  81.                 super.start();   
  82.                 return true;  
  83.             }  
  84.             else   
  85.                 return false;  
  86.         }  
  87.         else  
  88.             return false;  
  89.     }  
  90.     /* 
  91.      *从连接池得到一个连接 
  92.      */  
  93.     public synchronized Connection getConnection()  
  94.     {  
  95.           
  96.         if(init)  
  97.         {  
  98.             ConInfo c = getOneConnection();  
  99.             return c!=null?c.con:null;//安全得到一个连接  
  100.         }  
  101.         else  
  102.             return null;  
  103.     }  
  104.     /* 
  105.      *得到一个连接,包含了lastTime信息 
  106.      */  
  107.     protected synchronized ConInfo getOneConnection()  
  108.     {  
  109.         if(pool.size()!=0)  
  110.         {  
  111.             return pool.remove(0);  
  112.         }  
  113.         else //如果连接池为空,创建新的连接  
  114.         {  
  115.             if(debug) System.out.println("new connection!");  
  116.             return newConInfo();  
  117.         }  
  118.     }  
  119.     /* 
  120.      *将一个连接放回到连接池中 
  121.      */  
  122.     public synchronized boolean freeConnection(Connection con)  
  123.     {  
  124.         if(init==false || con == null )//当没有init或者已经close之后 不应该free它进来。  
  125.             return false;  
  126.         ConInfo c =  new ConInfo(con);//调用了ConInfo的构造函数  
  127.         pool.addElement(c);  
  128.         return true;  
  129.     }  
  130.     /* 
  131.      *将内容清空 
  132.      *且将本连接池对象置为无用状态 
  133.      */  
  134.     public synchronized  boolean close()  
  135.     {  
  136.         if(init)  
  137.         {  
  138.             init = false;  
  139.             for(int i = 0; i <pool.size();i++)  
  140.                 pool.get(i).close();  
  141.             pool.clear();  
  142.             pool    =   null;//将此连接池置为无用状态。如果要新的链接池,重新创建链接池对象  
  143.             dbname  =   null;  
  144.             user    =   null;  
  145.             psw     =   null;  
  146.             return true;  
  147.         }  
  148.         else   
  149.             return false;  
  150.     }  
  151.      
  152. ////////////////////////////////////////////////////////////////  
  153.     /* 
  154.      *下面将是一个一线程执行体,当start连接池服务之后,由它来维护 
  155.      *连接池里面的连接,从而保证他们能被正确的创建、注销 
  156.      * 
  157.      */  
  158.     public void run()  
  159.     {  
  160.         final long sleepTime = 2*1000  ; //2秒   
  161.         final long refreshTime = 10*60*1000//10分钟运行一次。连接是否应该被更新  
  162.         final long lowsCheckTime = 2*1000;//10秒检查一次。最低连接数检查间隔时间  
  163.         final long maxsCheckTime = 60*1000;//1分钟检查一次。最大连接数时间  
  164.         long loop = 0;  
  165.         while(true)  
  166.         {  
  167.             if(loop%refreshTime == 0)  
  168.             {  
  169.                 if(debug) System.out.println("call refresh:"+pool.size());  
  170.                 refreshByTimeDiff();  
  171.             }  
  172.             if(loop%maxsCheckTime == 0)  
  173.             {  
  174.                 if(debug) System.out.println("call toMaxs:"+pool.size());  
  175.                 toMaxs();  
  176.             }  
  177.             if(loop%lowsCheckTime == 0)  
  178.             {  
  179.                 if(debug) System.out.println("conCnt:"+conCount+" call toLows:"+pool.size());  
  180.                 toLows();  
  181.             }  
  182.             loop += sleepTime;//更新loop的时间。  
  183.             try{  
  184.                 sleep(sleepTime);  
  185.             }  
  186.             catch(Exception e){  
  187.                 e.printStackTrace();  
  188.                 stop();  
  189.             }  
  190.               
  191.         }  
  192.           
  193.     }  
  194.     /* 
  195.      *使过小的空闲连接数恢复到lows 
  196.      */  
  197.     protected void toLows()  
  198.     {  
  199.         int size = pool.size();  
  200.         /* 
  201.          *这里要避免直接使用pool.size进行判断 
  202.          *当连接一直被get出去之后,size很难达到lows,故此 
  203.          */  
  204.         for(;size<lows;size++)  
  205.         {  
  206.             if(debug) System.out.println("toLows is running!");  
  207.             ConInfo c =  newConInfo();  
  208.             if(c!=null)  
  209.                 synchronized(pool)  
  210.                 {  
  211.                     pool.addElement(c);  
  212.                 }  
  213.         }  
  214.     }  
  215.     /* 
  216.      *使过多的空闲连接数恢复到maxs; 
  217.      */  
  218.     protected void toMaxs()  
  219.     {  
  220.         int size = pool.size();  
  221.         for(;size>maxs;size--)  
  222.         {  
  223.             if(debug) System.out.println("toMaxs is running!");  
  224.             try{  
  225.                 getConnection().close();  
  226.                 synchronized(conCount)//这里修改要同步好。  
  227.                 {  
  228.                     conCount --;  
  229.                 }  
  230.             }  
  231.             catch(Exception e)  
  232.             {  
  233.                 e.printStackTrace();  
  234.             }  
  235.         }  
  236.     }  
  237.     /* 
  238.      *查找当前的连接池,找到timeDiff时间内未使用过的连接,删除它们,如果连接数不足,将由toLows补齐 
  239.      *一个危险的线程不安全函数 
  240.      */  
  241.     public void refreshByTimeDiff()  
  242.     {  
  243.         Calendar nowTime = Calendar.getInstance();  
  244.         long now = nowTime.getTimeInMillis();  
  245.         for(int i=0;i<pool.size();i++)  
  246.         {  
  247.             ConInfo c = getOneConnection();  
  248.             if(now  - c.lastTime.getTimeInMillis() >=timeDiff)//删除它们  
  249.             {  
  250.                 if(debug) System.out.println("refresh the pool!,,,,,,,,");  
  251.                 synchronized(pool)//获得pool的锁  
  252.                 {  
  253.                     pool.remove(i).close();//使用了ConInfo中的关闭函数  
  254.                 }  
  255.             }  
  256.         }  
  257.     }  
  258.     /* 
  259.      *一个测试数据库连接是否可用的函数 
  260.      */  
  261.     protected boolean test()  
  262.     {  
  263.         int cnt = 10;  
  264.         Connection c;  
  265.         do{  
  266.             c = newConnection();  
  267.             cnt -- ;  
  268.         }while(c==null && cnt>=0);  
  269.         if(c!=null)  
  270.         {  
  271.             (new ConInfo(c)).close();  
  272.             return true;  
  273.         }  
  274.         else  
  275.             return false;  
  276.               
  277.     }  
  278. ////////////////////////////////////////////////////////////////  
  279.     /* 
  280.      *下面为内置的类,用于表明一个连接最后使用时间 
  281.      */  
  282.     class ConInfo  
  283.     {  
  284.         protected Calendar lastTime;    //连接最后使用时间  
  285.         protected Connection con = null;    //对应的connection  
  286.         public ConInfo(Connection c)  
  287.         {  
  288.             con =   c;  
  289.             lastTime = Calendar.getInstance();  
  290.         }  
  291.         public synchronized void close()  
  292.         {  
  293.             try  
  294.             {  
  295.                 if(con!=null)  
  296.                     con.close();  
  297.                 synchronized(conCount)  
  298.                 {  
  299.                     conCount-=con!=null?1:0;  
  300.                 }  
  301.                 lastTime = null;  
  302.             }  
  303.             catch(Exception e)  
  304.             {  
  305.                 e.printStackTrace();  
  306.             }  
  307.         }  
  308.     }  
  309.     /* 
  310.      *创建一个新的连接 
  311.      */  
  312.     protected  Connection newConnection()  
  313.     {  
  314.         try  
  315.         {  
  316.             Class.forName("com.mysql.jdbc.Driver");  
  317.             int cnt = 0;  
  318.             Connection c = null;  
  319.             synchronized(conCount)  
  320.             {  
  321.                 if(conCount<=maxc)//当连接数没超过既定最大连接数时  
  322.                 do  
  323.                 {  
  324.                     try{  
  325.                     c = DriverManager.getConnection(dbname,user,psw);  
  326.                     }catch(Exception es){c=null;if(debug) System.out.println("create new connection error!");}  
  327.                     cnt++;  
  328.                 }while(null == c  && cnt<3);  
  329.                 conCount+=c!=null?1:0;  
  330.             }  
  331.             return c;//创建一个新的connection  
  332.         }  
  333.         catch(Exception e)  
  334.         {  
  335.             e.printStackTrace();  
  336.             return null;  
  337.         }  
  338.     }  
  339.     /* 
  340.      *得到一个新的连接 
  341.      */  
  342.     protected ConInfo newConInfo()  
  343.     {  
  344.         Connection c = newConnection();  
  345.         if(c==null)  
  346.             return null;  
  347.         return new ConInfo(c);  
  348.     }  
  349. ////////////////////////////////////////////////////  
  350.     /* 
  351.      *测试函数main 
  352.      */  
  353.     public static void main(String[] argvs)  
  354.     {  
  355.         VectorPool pool = new VectorPool();  
  356.         Connection con = null;  
  357.         boolean flag = pool.start("jdbc:mysql://localhost/finance","root","");  
  358.         int cnt = 10000;//1万次  
  359.         long t0  = Calendar.getInstance().getTimeInMillis();  
  360.         /////////测试选项  
  361.         final boolean tflag = true ;//如为true 为使用连接池  否则直接创建一个新连接。  
  362.         //////////////////////////////////////////////////////////////////////////  
  363.         while(flag){  
  364.           
  365.             con = tflag ? pool.getConnection():pool.newConnection();//;  
  366.             try  
  367.             {     
  368.                 Statement stm = con.createStatement();  
  369.                 ResultSet rev = stm.executeQuery("select * from user");  
  370.                 while(false && rev!=null && rev.next())  
  371.                 {  
  372.                     System.out.println(rev.getString("id"));  
  373.                 }  
  374.                 stm.close();  
  375.             }  
  376.             catch(Exception e)  
  377.             {  
  378.                 e.printStackTrace();  
  379.                   
  380.             }  
  381.         //  if(Math.abs(Math.random())%10<4)  
  382.             if(tflag)//使用完之后要释放,否则会出大问题  
  383.                 pool.freeConnection(con);  
  384.             try{  
  385.                 if(!tflag)  
  386.                     con.close();//释放连接 当不用pool时  
  387.             }  
  388.             catch(Exception exx)  
  389.             {  
  390.                 exx.printStackTrace();  
  391.             }  
  392.             /* 
  393.             try{ 
  394.                 sleep(100); ///间隔时间 
  395.             } 
  396.             catch(Exception ee) 
  397.             { 
  398.                 ee.printStackTrace(); 
  399.             } 
  400.             */  
  401.             //System.out.println("cnt:"+cnt);  
  402.         //  System.out.println("con_Cnt:"+pool.getConCount());  
  403.             if(--cnt<0)  
  404.                 break;  
  405.         }  
  406.         System.out.println("used time:"+(Calendar.getInstance().getTimeInMillis()-t0));  
  407.     }  
  408. }  
  409. /* 
  410.  * 
  411. use the pool; 
  412. cnt:3 
  413. cnt:2 
  414. cnt:1 
  415. cnt:0 
  416. used time:11286 
  417. ---用了11.286秒 
  418. cnt:9 
  419. cnt:8 
  420. cnt:7 
  421. cnt:6 
  422. cnt:5 
  423. cnt:4 
  424. cnt:3 
  425. cnt:2 
  426. cnt:1 
  427. cnt:0 
  428. used time:129376 
  429. 用了129.376秒(多了整整十倍)。 
  430. 再测试一次: 
  431. cnt:1 
  432. cnt:0 
  433. used time:7871  
  434. ---used the pool  7.871秒 
  435. cnt:4 
  436. cnt:3 
  437. cnt:2 
  438. cnt:1 
  439. cnt:0 
  440. used time:100084  
  441. ----create the connection one by one   100.084秒 
  442. */  

 

 

 

第二个实现类:ListPool

 

 

  1. /* 
  2.  * @(#)Pool.java 
  3.  * 
  4.  * 
  5.  * @author  
  6.  * @version 1.00 2010/5/15 
  7.  */  
  8. package mysql;  
  9. import mysql.*;  
  10. import java.sql.*;  
  11. import java.util.*;  
  12. /* 
  13.  *这里将实现ConnectionPool接口 
  14.  */  
  15. public class ListPool extends Thread implements Pool   
  16. {  
  17.     protected final boolean debug = false//是否debug态(如是  输出debug状态信息)  
  18.     protected boolean init = false;//是否已经将setting初始化  
  19.     //timeDiff   一个连接超过此时间未使用过,则需要更新此连接----1小时  
  20.     protected final long timeDiff =  60*60*1000 ;//1小时60分钟,1分钟60秒,1秒1000毫秒  
  21.     protected int lows = 20 ; //连接池的最小空闲连接数  
  22.     protected int maxs = 100 ; //连接池的最大空闲连接数  
  23.     protected int maxc = 100;  
  24.     protected String dbname = null;  
  25.     protected String user = null;  
  26.     protected String psw = null;  
  27.       
  28.     protected Integer conCount = 0//这个是静态的。当前连接数  
  29.     //下面是连接保存的池  
  30.     protected LinkedList<ConInfo> pool = new LinkedList<ConInfo>();  
  31.     public ListPool()   
  32.     {  
  33.     }  
  34.     public void start()  
  35.     {  
  36.           
  37.     }  
  38.     //得到当前连接数  
  39.     protected int getConCount()  
  40.     {  
  41.         return conCount;  
  42.     }  
  43.     /* 
  44.      *设置数据库连接的基本参数 
  45.      */  
  46.     public  synchronized  boolean start(String db,String u,String p)  
  47.     {  
  48.         if(false == init && null != pool)//如果未初始化,且连接池可用  
  49.         {  
  50.             dbname  =   db;  
  51.             user    =   u;  
  52.             psw     =   p;  
  53.             if(test())  
  54.             {  
  55.                 init    =   true;  
  56.                 super.start();   
  57.                 return true;  
  58.             }  
  59.             else return false;  
  60.         }  
  61.         else  
  62.             return false;  
  63.     }  
  64.     public synchronized boolean start(int l,int m,int mc,String db,String u,String p)  
  65.     {  
  66.         if(l<0 || m<0 ||l>=m || m>mc)//0<l<m<=mc  
  67.             return false;  
  68.         if(false == init && null != pool)//如果未初始化,且连接池可用  
  69.         {  
  70.             dbname  =   db;  
  71.             user    =   u;  
  72.             psw     =   p;  
  73.             if(test())  
  74.             {  
  75.                 init    =   true;  
  76.                 lows = l<5?5:l;  //这里允许的最小的值为5  
  77.                 maxs = m<10?10:m; //这里允许的最小的值为10  
  78.                 maxc = mc<

抱歉!评论已关闭.