博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java的JDBC数据库连接池实现方法
阅读量:4076 次
发布时间:2019-05-25

本文共 9700 字,大约阅读时间需要 32 分钟。

关键字:Java,JDBC,ConnectionPool,Database,数据库连接池,sourcecode

  虽然J2EE程序员一般都有现成的应用服务器所带的JDBC数据库连接池,不过对于开发一般的JavaApplication、Applet或者JSP、velocity时,我们可用的JDBC数据库连接池并不多,并且一般性能都不好。Java程序员都很羡慕WindowsADO,只需要newConnection就可以直接从数据库连接池中返回Connection。并且ADOConnection是线程安全的,多个线程可以共用一个Connection,所以ASP程序一般都把getConnection放在Global.asa文件中,在IIS启动时建立数据库连接。ADO的Connection和Result都有很好的缓冲,并且很容易使用。

其实我们可以自己写一个JDBC数据库连接池。写JDBCconnectionpool的注意事项有:

1.有一个简单的函数从连接池中得到一个Connection。

2.close函数必须将connection放回数据库连接池。
3.当数据库连接池中没有空闲的connection,数据库连接池必须能够自动增加connection个数。
4.当数据库连接池中的connection个数在某一个特别的时间变得很大,但是以后很长时间只用其中一小部分,应该可以自动将多余的connection关闭掉。
5.如果可能,应该提供debug信息报告没有关闭的newConnection。

如果要newConnection就可以直接从数据库连接池中返回Connection,可以这样写(Mediatorpattern)(以下代码中使用了中文全角空格):

publicclassEasyConnectionimplementsjava.sql.Connection{

  privateConnectionm_delegate=null;

  publicEasyConnection(){

    m_delegate=getConnectionFromPool();
  }

  publicvoidclose(){

    putConnectionBackToPool(m_delegate);
  }

  publicPreparedStatementprepareStatement(Stringsql)throwsSQLException{

    m_delegate.prepareStatement(sql);
  }

  //......othermethod

}

看来并不难。不过不建议这种写法,因为应该尽量避免使用JavaInterface,关于JavaInterface的缺点我另外再写文章讨论。大家关注的是ConnectionPool的实现方法。下面给出一种实现方法。

importjava.sql.*;

importjava.lang.reflect.*;
importjava.util.*;
importjava.io.*;

publicclassSimpleConnetionPool{

  privatestaticLinkedListm_notUsedConnection=newLinkedList();
  privatestaticHashSetm_usedUsedConnection=newHashSet();
  privatestaticStringm_url="";
  privatestaticStringm_user="";
  privatestaticStringm_password="";
  staticfinalbooleanDEBUG=true;
  staticprivatelongm_lastClearClosedConnection=System.currentTimeMillis();
  publicstaticlongCHECK_CLOSED_CONNECTION_TIME=4*60*60*1000;//4hours

  static{

    initDriver();
  }

  privateSimpleConnetionPool(){

  }

  privatestaticvoidinitDriver(){

    Driverdriver=null;
    //loadmysqldriver
    try{
      driver=(Driver)Class.forName("com.mysql.jdbc.Driver").newInstance();
      installDriver(driver);
    }catch(Exceptione){
    }

    //loadpostgresqldriver

    try{
      driver=(Driver)Class.forName("org.postgresql.Driver").newInstance();
      installDriver(driver);
    }catch(Exceptione){
    }
  }

  publicstaticvoidinstallDriver(Driverdriver){

    try{
      DriverManager.registerDriver(driver);
    }catch(Exceptione){
      e.printStackTrace();
    }
  }

  publicstaticsynchronizedConnectiongetConnection(){
    clearClosedConnection();
    while(m_notUsedConnection.size()>0){
      try{
        ConnectionWrapperwrapper=(ConnectionWrapper)m_notUsedConnection.removeFirst();
        if(wrapper.connection.isClosed()){
          continue;
        }
        m_usedUsedConnection.add(wrapper);
        if(DEBUG){
          wrapper.debugInfo=newThrowable("Connectioninitialstatement");
        }
        returnwrapper.connection;
      }catch(Exceptione){
      }
    }
    intnewCount=getIncreasingConnectionCount();
    LinkedListlist=newLinkedList();
    ConnectionWrapperwrapper=null;
    for(inti=0;i<newCount;i++){
      wrapper=getNewConnection();
      if(wrapper!=null){
        list.add(wrapper);
      }
    }
    if(list.size()==0){
      returnnull;
    }
    wrapper=(ConnectionWrapper)list.removeFirst();
    m_usedUsedConnection.add(wrapper);

    m_notUsedConnection.addAll(list);

    list.clear();

    returnwrapper.connection;

  }

  privatestaticConnectionWrappergetNewConnection(){

    try{
      Connectioncon=DriverManager.getConnection(m_url,m_user,m_password);
      ConnectionWrapperwrapper=newConnectionWrapper(con);
      returnwrapper;
    }catch(Exceptione){
      e.printStackTrace();
    }
    returnnull;
  }

  staticsynchronizedvoidpushConnectionBackToPool(ConnectionWrappercon){

    booleanexist=m_usedUsedConnection.remove(con);
    if(exist){
      m_notUsedConnection.addLast(con);
    }
  }

  publicstaticintclose(){

    intcount=0;

    Iteratoriterator=m_notUsedConnection.iterator();

    while(iterator.hasNext()){
      try{
        ((ConnectionWrapper)iterator.next()).close();
        count++;
      }catch(Exceptione){
      }
    }
    m_notUsedConnection.clear();

    iterator=m_usedUsedConnection.iterator();

    while(iterator.hasNext()){
      try{
        ConnectionWrapperwrapper=(ConnectionWrapper)iterator.next();
        wrapper.close();
        if(DEBUG){
          wrapper.debugInfo.printStackTrace();
        }
        count++;
      }catch(Exceptione){
      }
    }
    m_usedUsedConnection.clear();

    returncount;

  }

  privatestaticvoidclearClosedConnection(){

    longtime=System.currentTimeMillis();
    //sometimesuserchangesystemtime,justreturn
    if(time<m_lastClearClosedConnection){
      time=m_lastClearClosedConnection;
      return;
    }
    //noneedcheckveryoften
    if(time-m_lastClearClosedConnection<CHECK_CLOSED_CONNECTION_TIME){
      return;
    }
    m_lastClearClosedConnection=time;

    //begincheck

    Iteratoriterator=m_notUsedConnection.iterator();
    while(iterator.hasNext()){
      ConnectionWrapperwrapper=(ConnectionWrapper)iterator.next();
      try{
        if(wrapper.connection.isClosed()){
          iterator.remove();
        }
      }catch(Exceptione){
        iterator.remove();
        if(DEBUG){
          System.out.println("connectionisclosed,thisconnectioninitialStackTrace");
          wrapper.debugInfo.printStackTrace();
        }
      }
    }

    //makeconnectionpoolsizesmalleriftoobig

    intdecrease=getDecreasingConnectionCount();
    if(m_notUsedConnection.size()<decrease){
      return;
    }

    while(decrease-->0){

      ConnectionWrapperwrapper=(ConnectionWrapper)m_notUsedConnection.removeFirst();
      try{
        wrapper.connection.close();
      }catch(Exceptione){
      }
    }
  }

  /**

  *getincreasingconnectioncount,notjustadd1connection
  *@returncount
  */
  publicstaticintgetIncreasingConnectionCount(){
    intcount=1;
    intcurrent=getConnectionCount();
    count=current/4;
    if(count<1){
      count=1;
    }
    returncount;
  }

  /**

  *getdecreasingconnectioncount,notjustremove1connection
  *@returncount
  */
  publicstaticintgetDecreasingConnectionCount(){
    intcount=0;
    intcurrent=getConnectionCount();
    if(current<10){
      return0;
    }
    returncurrent/3;
  }

  publicsynchronizedstaticvoidprintDebugMsg(){

    printDebugMsg(System.out);
  }

  publicsynchronizedstaticvoidprintDebugMsg(PrintStreamout){

    if(DEBUG==false){
      return;
    }
    StringBuffermsg=newStringBuffer();
    msg.append("debugmessagein"+SimpleConnetionPool.class.getName());
    msg.append("/r/n");
    msg.append("totalcountisconnectionpool:"+getConnectionCount());
    msg.append("/r/n");
    msg.append("notusedconnectioncount:"+getNotUsedConnectionCount());
    msg.append("/r/n");
    msg.append("usedconnection,count:"+getUsedConnectionCount());
    out.println(msg);
    Iteratoriterator=m_usedUsedConnection.iterator();
    while(iterator.hasNext()){
      ConnectionWrapperwrapper=(ConnectionWrapper)iterator.next();
      wrapper.debugInfo.printStackTrace(out);
    }
    out.println();
  }

  publicstaticsynchronizedintgetNotUsedConnectionCount(){

    returnm_notUsedConnection.size();
  }

  publicstaticsynchronizedintgetUsedConnectionCount(){

    returnm_usedUsedConnection.size();
  }

  publicstaticsynchronizedintgetConnectionCount(){

    returnm_notUsedConnection.size()+m_usedUsedConnection.size();
  }

  publicstaticStringgetUrl(){

    returnm_url;
  }

  publicstaticvoidsetUrl(Stringurl){

    if(url==null){
      return;
    }
    m_url=url.trim();
  }

  publicstaticStringgetUser(){

    returnm_user;
  }

  publicstaticvoidsetUser(Stringuser){

    if(user==null){
      return;
    }
    m_user=user.trim();
  }

  publicstaticStringgetPassword(){

    returnm_password;
  }

  publicstaticvoidsetPassword(Stringpassword){

    if(password==null){
      return;
    }
    m_password=password.trim();
  }

}

classConnectionWrapperimplementsInvocationHandler{

  privatefinalstaticStringCLOSE_METHOD_NAME="close";
  publicConnectionconnection=null;
  privateConnectionm_originConnection=null;
  publiclonglastAccessTime=System.currentTimeMillis();
  ThrowabledebugInfo=newThrowable("Connectioninitialstatement");

  ConnectionWrapper(Connectioncon){

    Class[]interfaces={java.sql.Connection.class};
    this.connection=(Connection)Proxy.newProxyInstance(
      con.getClass().getClassLoader(),
      interfaces,this);
    m_originConnection=con;
  }

  voidclose()throwsSQLException{

    m_originConnection.close();
  }

  publicObjectinvoke(Objectproxy,Methodm,Object[]args)throwsThrowable{

    Objectobj=null;
    if(CLOSE_METHOD_NAME.equals(m.getName())){
      SimpleConnetionPool.pushConnectionBackToPool(this);
    }
    else{
      obj=m.invoke(m_originConnection,args);
    }
    lastAccessTime=System.currentTimeMillis();
    returnobj;
  }
}

使用方法

publicclassTestConnectionPool{

  publicstaticvoidmain(String[]args){
    SimpleConnetionPool.setUrl(DBTools.getDatabaseUrl());
    SimpleConnetionPool.setUser(DBTools.getDatabaseUserName());
    SimpleConnetionPool.setPassword(DBTools.getDatabasePassword());

    Connectioncon=SimpleConnetionPool.getConnection();

    Connectioncon1=SimpleConnetionPool.getConnection();
    Connectioncon2=SimpleConnetionPool.getConnection();

    //dosomethingwithcon...

    try{

      con.close();
    }catch(Exceptione){}

    try{

      con1.close();
    }catch(Exceptione){}

    try{

      con2.close();
    }catch(Exceptione){}

    con=SimpleConnetionPool.getConnection();

    con1=SimpleConnetionPool.getConnection();
    try{
      con1.close();
    }catch(Exceptione){}

    con2=SimpleConnetionPool.getConnection();

    SimpleConnetionPool.printDebugMsg();

  }

}

运行测试程序后打印连接池中Connection状态,以及正在使用的没有关闭Connection信息。

转载地址:http://ookni.baihongyu.com/

你可能感兴趣的文章
堆排序完整版,含注释
查看>>
二叉树深度优先遍历和广度优先遍历
查看>>
生产者消费者模型,循环队列实现
查看>>
PostgreSQL代码分析,查询优化部分,process_duplicate_ors
查看>>
PostgreSQL代码分析,查询优化部分,canonicalize_qual
查看>>
PostgreSQL代码分析,查询优化部分,pull_ands()和pull_ors()
查看>>
IA32时钟周期的一些内容
查看>>
获得github工程中的一个文件夹的方法
查看>>
《PostgreSQL技术内幕:查询优化深度探索》养成记
查看>>
PostgreSQL查询优化器详解之逻辑优化篇
查看>>
STM32中assert_param的使用
查看>>
C语言中的 (void*)0 与 (void)0
查看>>
vu 是什么
查看>>
io口的作用
查看>>
IO口的作用
查看>>
UIView的使用setNeedsDisplay
查看>>
归档与解归档
查看>>
Window
查看>>
为什么button在设置标题时要用一个方法,而不像lable一样直接用一个属性
查看>>
字符串的截取
查看>>