在线用户    站点地图 技术论坛 文档中心 站点导航 资源下载 语言参考 教程专题 站点统计 业务项目 使用帮助
您的位置
MSDN参考新加了CSS2参考,全中文,制作精良。245k下载。           新加了sxf_sxf推荐的"动态网页专家指导" 下载!          新加了lsg2002lsg推荐的"ASP.NET高级编程(PDF)" 下载!          新加了DHTML代码预览!!,功能强大哦!欢迎试用          新加了网友lincong为大家提供的SQL Server 2000 程序员指南,有点大,但同时也就说明内容全咯!           新加了网友ibra为大家提供的北大的JAVA课件,很适合初学者入门           新加了一个java的连接缓冲池代码示例           新加了人月神话电子版下载!软件工程巨著哦~~           更新了评分标准,引入了“专家分”概念,相信可以更好的激励大家的学习!详情请看“使用帮助”           新加了由网友GGG提供的“IIS超级管理手册”,值得一看哦!(虽然我没看过 :P )           新加了“英雄榜”,欢迎测试!           “无组件上传·从原理剖析到实践”已经全部完成,源码全部开放,有兴趣的朋友请到文档中心一探究竟。  您的位置  首页>文档中心>JAVA>文档A0000558 在同一窗口中打开页面中的链接 在新窗口中打开页面中的链接 将ASPCHINA设为首页 将ASPCHINA加入书签    
 LOGIN HERE
用户:
密码: 忘记密码
记住密码 用户注册 游客进入
相关文章

jTDS mssqlserver/sybase 10 JDBC 驱动下载(最好的mssqlserver jdbc driver)

在2003下用JDBC访问本机MS SQL

通过JDBC操纵Oracle数据库LOB字段的几种情况分析

不建立系统DSN,通过JDBCODBC bridge连接数据库

SQLSERVER 2000的JDBC驱动

ActiveConnection&CursorType 说明
发表文章
一个连接池的实现

作者:miles     提交人:miles     发布时间:04-01-02     文章类型:原创     浏览量:8391
参考链结:http://    
关键字:pool|连接池|缓冲池|connection|jdbc
[本文档没有附件]
字体:    视力保护色: 杏仁黄  秋叶褐  胭脂红  芥末绿  天蓝  雪青  灰  银河白(默认色) [A0000558]

connection pool对于提高数据库访问性能是至关重要的,现在已经是普遍采用了。了解一下他的原理,既有现实意义,也有理论意义。

这是我参考一些例子写的一个pool。里面有些系统相关的东西,所以不能直接用。不过我希望大家能了解到他的原理,所以也就没去掉。

另外,这个类写的较早,也没有按规范写javadoc。但是注释改写的基本写全了。大家发布的时候,自己转换一下吧。

package com.yup.lib.dataaccess;

import java.sql.*;
import java.util.*;

import com.yup.lib.*;
import com.yup.lib.debug.*;

/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2001</p>
* <p>Company: YupStudio.</p>
* @author Miles.Chang
* @version 1.00
*/

public class ConnectionPool implements Runnable {

  // instead of util.ArrayList, we use Vector because it is synchronized.
  private Vector availableConnections, busyConnections;
  // a flag.
  private boolean connectionPending = false;

  // a counter for fatigue connection releasing.
  private int freeTimes = 0;

  // default configuration of the pool.
  private final static int DEF_REUSE_UP_LIMIT = 500;
  private final static int DEF_INIT_CONNECTIONS = 1;
  private final static int DEF_MAX_CONNECTIONS = 5;
  private final static boolean DEF_WAIT_IF_BUSY = true;

  // variables for establishing the connection.
  private String driver;
  private String url;
  private String username;
  private String password;

  // pool configuration variables.
  private int initConnections;
  private int reuseUpLimit;
  private int maxConnections;
  private boolean waitIfBusy;

  // the driver.
  private Driver drvDriver;

  // exception descriptions.
  private static final String EX_INVALID_INIT_PARAM = "invalid initialzing parameter.";
  private final static String EX_LIMIT_REACHED = "Connection limit reached";
  private final static String EX_DRIVER_NOT_FOUND = "Can't find class for driver: ";
  private final static String EX_POOL_NOT_INIT = "Connection pool has not been initialized.";
  private final static String EX_POOL_HAS_INIT = "Connection pool has been initialized. You should close it up at first.";

  // singleton pattern.
  private ConnectionPool(String driver, String url,
                        String username, String password,
                        int initConnections, int reuseUpLimit,
                        int maxConnections, boolean waitIfBusy)
  throws SQLException {
//    NumberKit nk = NumberKit.getInstance();
//
//    try {
//      driver = Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.driver");
//      url = Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.url");
//      username = Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.username");
//      password = Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.password");
//    } catch(MissingResourceException ex) {
//      throw new MissingResourceException("com.yup.lib.dataaccess.ConnectionPool(): " + ex.getMessage(), ex.getClassName(), ex.getKey());
//    }
//
//    try {
//      initConnections = nk.getInt(Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.initConnections"));
//    } catch(MissingResourceException ex) {
//      initConnections = DEF_INIT_CONNECTIONS;
//    }
//
//    try {
//      reuseUpLimit = nk.getInt(Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.reuseUpLimit"));
//    } catch(MissingResourceException ex) {
//      reuseUpLimit = DEF_REUSE_UP_LIMIT;
//    }
//
//    try {
//      maxConnections = nk.getInt(Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.maxConnections"));
//    } catch(MissingResourceException ex) {
//      maxConnections = DEF_MAX_CONNECTIONS;
//    }
//
//    try {
//      waitIfBusy = Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.waitIfBusy").trim().equalsIgnoreCase("TRUE");
//    } catch(MissingResourceException ex) {
//      waitIfBusy = DEF_WAIT_IF_BUSY;
//    }

    if(availableConnections!=null&&availableConnections.size()>0) {
      throw new SQLException("com.yup.lib.dataaccess.ConnectionPool(): " + EX_POOL_HAS_INIT);
    }

    this.driver = driver;
    this.url = url;
    this.username = username;
    this.password = password;
    this.initConnections = initConnections<0?DEF_INIT_CONNECTIONS:initConnections;
    this.reuseUpLimit = reuseUpLimit<1?DEF_REUSE_UP_LIMIT:reuseUpLimit;
    this.maxConnections = maxConnections<1?DEF_MAX_CONNECTIONS:maxConnections;
    this.waitIfBusy = waitIfBusy;

    if(this.initConnections>this.maxConnections) {
      throw new IllegalArgumentException("com.yup.lib.dataaccess.ConnectionPool(): " + EX_INVALID_INIT_PARAM);
    }

    loadDriver();

    availableConnections = new Vector(this.initConnections);
    busyConnections = new Vector();
    for (int i=0;i<this.initConnections;i++) {
      availableConnections.addElement(makeNewConnection());
    }
  }

  // for singleton pattern.
  private static Object initLock = new Object();
  private static ConnectionPool pool;

  // a typical double-checked locking block. HERE'S A TRAP!!
  public static ConnectionPool getInstance()
  throws SQLException {
    if(pool==null) {
      throw new SQLException("com.yup.lib.dataaccess.getInstance(): " + EX_POOL_NOT_INIT);
    }
    return pool;
  }

  // pool initializtion. this method should be called before using the pool.
  public static void init(String driver, String url,
                          String username, String password,
                          int initConnections, int reuseUpLimit,
                          int maxConnections, boolean waitIfBusy)
  throws SQLException {
    if(pool==null) {
      synchronized(initLock) {
        if(pool==null) pool = new ConnectionPool(driver, url, username, password, initConnections, reuseUpLimit, maxConnections, waitIfBusy);
      }
    }
  }

  // get a connection.
  public synchronized Connection getActiveConnection()
  throws SQLException {
    if (!availableConnections.isEmpty()) {
      Connection existingConnection = (Connection)availableConnections.lastElement();
      int lastIndex = availableConnections.size()-1;
      availableConnections.removeElementAt(lastIndex);
      // If connection on available list is closed (e.g.,it timed out), then
      // remove it from available list and repeat the process of obtaining a
      // connection.Also wake up threads that were waiting for a connection
      // because maxConnection limit was reached.
      if (existingConnection.isClosed()) {
        Logger.debug("Exist connection closed, notify all and get a new free connection.");
        notifyAll(); // Freed up a spot for anybody waiting
        return(getActiveConnection());
      } else {
        busyConnections.addElement(existingConnection);

        // debug when connection get.
        Logger.debug("Get connection successfully!");
        Logger.debug("Total connection: ");
        Logger.debug(""+this.totalConnections());
        Logger.debug("Available connections: ");
        Logger.debug(""+availableConnections.size());
        Logger.debug("Busy connections: ");
        Logger.debug(""+busyConnections.size());
        Logger.debug("");
        return(existingConnection);
      }
    } else {

      // Three possible cases:
      // 1) You haven't reached maxConnections limit. So
      //    establish one in the background if there isn't
      //    already one pending, then wait for
      //    the next available connection (whether or not
      //    it was the newly established one).
      // 2) You reached maxConnections limit and waitIfBusy
      //    flag is false. Throw SQLException in such a case.
      // 3) You reached maxConnections limit and waitIfBusy
      //    flag is true. Then do the same thing as in second
      //    part of step 1: wait for next available connection.
      if ((totalConnections()<maxConnections)&&!connectionPending) {
        makeBackgroundConnection();
      } else if (!waitIfBusy) {
        throw new SQLException("com.yup.lib.dataaccess.ConnectionPool.getActiveConnection(): "+EX_LIMIT_REACHED);
      }
      // Wait for either a new connection to be established
      // (if you called makeBackgroundConnection) or for
      // an existing connection to be freed up.
      try {
        Logger.debug("No Availible Connection, Waiting...");
        wait();
      } catch(InterruptedException ie) {}
      // Someone freed up a connection, so try again.
      return(getActiveConnection());
    }
  }

  // You can't just make a new connection in the foreground
  // when none are available, since this can take several
  // seconds with a slow network connection. Instead,
  // start a thread that establishes a new connection,
  // then wait. You get woken up either when the new connection
  // is established or if someone finishes with an existing
  // connection.
  private void makeBackgroundConnection() {
    connectionPending = true;
    try {
      Thread connectThread = new Thread(this);
      connectThread.start();
    } catch(OutOfMemoryError ex) {
      Logger.debug("com.yup.lib.dataaccess.ConnectionPool.makeBackgroundConnection(): Out of memory error:" + ex.toString());
      // Give up on new connection
    }
  }

  // start a thread.
  public void run() {
    try {
      Connection connection = makeNewConnection();
      synchronized(this) {
        availableConnections.addElement(connection);
        connectionPending = false;
        notifyAll();
      }
    } catch(Exception ex) { // SQLException or OutOfMemory
      // Give up on new connection and wait for existing one
      // to free up.
      Logger.debug("com.yup.lib.dataaccess.ConnectionPool.run(): " + ex.toString());
    }
  }

  // This explicitly makes a new connection. Called in
  // the foreground when initializing the ConnectionPool,
  // and called in the background when running.
  private Connection makeNewConnection()
  throws SQLException {
    // Establish network connection to database
    Connection connection = DriverManager.getConnection(url, username, password);
    Logger.debug("Make new connection successfully!");
    return(connection);
  }

  // Driver loading.
  private void loadDriver()
  throws SQLException {
    try {
      // Load database driver if not already loaded
      drvDriver = (Driver)Class.forName(driver).newInstance();
      DriverManager.registerDriver(drvDriver);
      Logger.debug("Load driver succcessfully!");
    } catch(ClassNotFoundException ex) {
      // Simplify try/catch blocks of people using this by
      // throwing only one exception type.
      throw new SQLException("com.yup.lib.dataaccess.ConnectionPool.makeNewConnection():" + EX_DRIVER_NOT_FOUND + driver);
    } catch(IllegalAccessException ex) {
      // Simplify try/catch blocks of people using this by
      // throwing only one exception type.
      throw new SQLException("com.yup.lib.dataaccess.ConnectionPool.makeNewConnection():" + ex.getMessage());
    } catch(InstantiationException ex) {
      // Simplify try/catch blocks of people using this by
      // throwing only one exception type.
      throw new SQLException("com.yup.lib.dataaccess.ConnectionPool.makeNewConnection():" + ex.getMessage());
    }
  }

  // Driver releasing.
  private void releaseDriver()
  throws SQLException {
    DriverManager.deregisterDriver(drvDriver);
    Logger.debug("Release driver succcessfully!");
  }

  // Free up a connection.
  public synchronized void freeConnection(Connection connection) {
    busyConnections.removeElement(connection);
    availableConnections.insertElementAt(connection,0);
    // Wake up threads that are waiting for a connection
    Logger.debug("Free connection successfully, notifying...");
    Logger.debug("Total connection: ");
    Logger.debug(""+totalConnections());
    Logger.debug("Available connections: ");
    Logger.debug(""+availableConnections.size());
    Logger.debug("Busy connections: ");
    Logger.debug(""+busyConnections.size());

    // reach up limit.release.
    if(++freeTimes>reuseUpLimit) {
      freeTimes = 0;
      Logger.debug("================ Time to close some fatigued connections ===============");
      try {
        connection.close();
      } catch (SQLException ex) {
        Logger.debug("com.yup.lib.dataaccess.ConnectionPool.freeConnection(): " + ex.toString());
      }
    }

    // Available Connection
    Logger.debug("======================");
    Logger.debug("========== " + (reuseUpLimit-freeTimes) + "  ========");
    Logger.debug("======================");
    notifyAll();
  }

  // Get the count of current connections.
  public synchronized int totalConnections() {
    int intTotal = availableConnections.size() + busyConnections.size();
    return intTotal;
  }

  /** Close all the connections. Use with caution:
  *  be sure no connections are in use before
  *  calling. Note that you are not <I>required</I> to
  *  call this when done with a ConnectionPool, since
  *  connections are guaranteed to be closed when
  *  garbage collected. But this method gives more control
  *  regarding when the connections are closed.
  */
  private synchronized void closeAllConnections() {
    this.closeConnections(availableConnections);
    availableConnections = new Vector();
    this.closeConnections(busyConnections);
    busyConnections = new Vector();
  }

  // Destroy the pool.
  public static void destory()
  throws SQLException  {
    if(pool==null) {
      throw new SQLException("com.yup.lib.dataaccess.destory(): " + EX_POOL_NOT_INIT);
    }
    pool.closeAllConnections();
    pool.availableConnections = null;
    pool.busyConnections = null;
    pool.releaseDriver();
    pool = null;
  }

  // Close up all the connections.
  private void closeConnections(Vector connections) {
    try {
      for (int i=0; i<connections.size(); i++) {
        Connection connection = (Connection)connections.elementAt(i);
        if ( !connection.isClosed() ) {
          Logger.debug("Connection closed succcessfully!");
          connection.close();
        }
      }
    } catch(SQLException ex) {
        Logger.debug("com.yup.lib.dataaccess.ConnectionPool.freeConnection(): " + ex.toString());
      // Ignore errors; garbage collect anyhow
    }
  }

  // Get info.
  public String toString() {
    String info =
      "ConnectionPool(" + url + "," + username + ")" +
      ", available=" + availableConnections.size() +
      ", busy=" + busyConnections.size() +
      ", max=" + maxConnections;
    return(info);
  }

  // a test method.
  public static void main(String[] args) {
    try {
      String url="jdbc:odbc:Driver=Microsoft Access Driver (*.mdb);DBQ=D:\\__!!MILES!!__\\dev\\jdbc\\xxx.mdb";
      String driver = "sun.jdbc.odbc.JdbcOdbcDriver";
      Global.initDBPool(driver, url);
    } catch(Exception ex) {
      ex.printStackTrace();
    } finally {
      try{
        Global.destoryDBPool();
      } catch(SQLException ex) {
        ex.printStackTrace();
      }
    }
  }
}

关于这篇文章的评论 [注意:这里仅仅是给大家提供了一个发表对文章本身看法的地方,如果有疑问,请到论坛提出] 我要提问!
标题
内容
发言
*您尚未以注册用户身份登录,不能发表评论。这里登录
您的位置
  (c)2000-2018 Yup Studio, all rights reserved.  
433.5938