如果超过最大连接数,当然要让请求线程等待,要是等待线程过多嘛,系统允许的话可以增加最大连接。
下面是我平时常用的连接池基类,有不足之处,欢迎指正:
package mai.database.pool;
import mai.database.pool.ResourceException;
import java.util.*;public abstract class ResourcePool implements Runnable
{
protected final Vector availableResources=new Vector();
protected final Vector inUseResources=new Vector();
protected int maxResources;
private boolean waitOutTime;
private ResourceException error=null;
public ResourcePool()
{
this(10,true);
}
public ResourcePool(int max,boolean waitOutTime)
{
this.maxResources=max;
this.waitOutTime=waitOutTime;
}
public abstract Object createResource() throws ResourceException; public abstract boolean isAvailableResource(Object resource); public abstract void closeResource(Object resource); public Object getResource() throws ResourceException
{
return getResource(0);
} public Object getResource(long time) throws ResourceException
{
Object o=getFirstResource();
if(o==null)
{
if(countResources()<maxResources)
{
waitForAvailableResource();
return getResource();
}
else
{
if(waitOutTime)
{
try{
wait(time);
}
catch(Exception ex){System.out.println("资源已经用完,请等待...");}
return getResource();
}
throw new ResourceException("Maximum number of resources reached.Try again later.");
  }
}
inUseResources.addElement(o);
return o;
}
private Object getFirstResource()
{
Object o=null;
if(availableResources.size()>0)
{
o=availableResources.firstElement();
availableResources.remove(0);
}
if(o!=null && !isAvailableResource(o))
o=getFirstResource();
return o;
}
public synchronized void run()
{
Object o=null;
try{
o=createResource();
}
catch(ResourceException e)
{ error=e;
notifyAll();
return;
}
availableResources.addElement(o);
notifyAll();
}
public synchronized void recycleResource(Object resource)
{
inUseResources.remove(resource);
availableResources.addElement(resource);
try{
notifyAll();
}
catch(Exception e)
{System.out.println("the current thread is not the owner of this object's monitor.");
}
}
private void waitForAvailableResource() throws ResourceException
{
Thread t=new Thread(this);
t.start();
try{
wait();
}
catch(Exception e)
{System.out.println("Method waitForAvailableResource's wait() is error");}

if(error!=null)
throw error;
}
private synchronized void closeResources(Vector v)
{
Iterator it=v.iterator();
while(it.hasNext())
closeResource(it.next());
}
public synchronized  void showDown()
{
closeResources(availableResources);
closeResources(inUseResources);

availableResources.clear();
inUseResources.clear();
}
private int countResources()
{
return availableResources.size()+inUseResources.size();
}
}

解决方案 »

  1.   

    tianmenyzh(土豆丝):我说过抛除无意关闭连接的情况,有没有其他原因阻止使用全局的连接对象?主要是有没有基于数据库方面的原因
      

  2.   

    Mai_520(网海茫茫,我也忙忙!)  
    谢谢回复,你的例子我看了。对线程处理很恰当,值得学习。能不能把实现类的代码也拿出来。我想看看,你整个连接池都解决到什么地步。另外对你这个连接池的调用也放出来吧。还有没有对上述3个问题有见解的评论,请多讨论。
      

  3.   

    1、数据连接对象为什么要池化?为什么不使用一个全局的连接对象来取代连接池?(如果抛除事务提交回滚,和对connection对象的无意close这2个原因,有没有其他基于数据库譬如oracle的原因)使用一个全局的连接如果要同时用两个连接怎么办?如果有一个线程要比较长时间的占用连接怎么处理?最后还不是要实现和连接池类似的机制2、如果超过最大连接数,应该让请求(线程)等待。我们如何做呢?利用线程的特性还是其他方法?如果等待的线程过多是否需要线程池呢?应该增加池中连接数,如果超过最大数可以让线程等待或者抛出异常3、我们知道JDBC2.0提供了包含连接池功能的接口,由应用服务器(譬如weblogic\tomcat)来实现。就你所知它比传统的连接池强在那里?这里请加入你实际应用后的体会。最大的好处是不用自己写一个,但移植性就差了一点
      

  4.   

    Mai_520(网海茫茫,我也忙忙!):
    凭心而论你的线程池的实现实在太简单了!
    千万不要用于实际的应用!不安全!
      

  5.   

    AYellow(北斗猪) :谢谢你的回复,那我针对你的回复问几个问题
    1、同时用2个连接:我理解是这样客户端无论怎么调用这个全局的连接对象,在同一时间只能有一个连接取到数据。我不知道我理解的对不对,所谓同步最后总要归结为一个(指令)队列。所以这里同时使用连接的问题是在数据库当中解决的譬如oralce.
    一个线程长时间占用:可以使该连接不同步(no synchronize),那么是不是一个线程无法独占这个连接了。当然,我认为有诸如你提到的这些问题以及事务、无意close等足以说明连接池的必要了。但如果小心的情况下有没有必须使用连接池的必要呢?请继续讨论2、这个问题Mai_520(网海茫茫,我也忙忙!)已经给了一个例子,我看了。除了未对等待线程管理外基本没什么可说的。给等待线程加入一个线程池管理就一定好么?我也想知道答案3、移植性差这点你说的对。
      

  6.   

    Norwaywoods() 你对Mai_520的连接池基类不满意在那里呢?其实那是一个池化任意对象的基类。你能不能说具体一点。我对它在创建一个资源对象时使用线程感觉到不理解,就是下面这个方法。
    private void waitForAvailableResource() throws ResourceException
    {
    Thread t=new Thread(this);
    t.start();
    try{
    wait();
    另外不知道是不是没有定义释放资源的方法。 }我希望Mai_520把对这个连接池的调用过程放出来。让我们一目了然希望Norwaywoods()把自己好的例子也拿出来。:)
      

  7.   

    我老实交待,我没有自己的例子。但是我仔细的研究过一个实际应用中的Thread_Pool(大型后台程序,支持多CPU)。我比较了一下这两者的差异得出上面的结论。今天晚些时候我会给出详细的解释。
      

  8.   

    我认为一个像样的Server端的程序使用连接池是必须的,不管如何小心,也无法避免需要使用事务等情况不用费心去考虑不使用连接池怎么处理,因为使用连接池并不麻烦
      

  9.   

    谢谢北斗猪的回复,那么你定义了一个连接池的使用范围——server side.也许第一个问题的讨论就到此结束了。
    等待Norwaywoods()的结论,希望Norwaywoods()把那个Thread pool也引申的说一下,另外支持多CPU意味这什么呢?负载平衡么?如果是也把负载平衡相关原理及和thread pool和connection pool的关联说明一下。这个问题我也很想搞清楚,你可以由浅入深的来:)多谢其它同志有什么引申出来的问题,一并来讨论。
      

  10.   

    我的例子确实有些简单了,写它是我用来给自己的主页而用的,由于几乎不用涉及到安全性,所以有许多不当之处,欢迎讨论。
    下面是我的实现类:
    package mai.database.pool;
    import mai.database.pool.*;
    import java.sql.*;
    import java.util.*;public class DatabaseConnPool extends ResourcePool
    {
    private String sDBDriver="";
    private String url="";
    private int initResources=5;
    private boolean isLoadDriver=false;

    private String user="",password=""; public DatabaseConnPool(String sdb,String url)
    {
    this(sdb,url,"","",10);
    } public DatabaseConnPool(String sdb,String url,String user,String password,int maxResources)
    {
    this.sDBDriver=sdb;
    this.url=url;
    this.user=user;
    this.password=password;
    this.maxResources=maxResources; 
    System.out.println("[Connection Pool | inited Connection:"+initResources+" | max Connection:"+maxResources+"]");
    for(int i=0;i<initResources;i++)
    {
    availableResources.addElement(createResource());
    } } public Object createResource()
    {
    Connection conn=null;
    if(!isLoadDriver)
    {
    try{
    Class.forName(sDBDriver);
    isLoadDriver=true;
    }
    catch(ClassNotFoundException e){System.out.println(e.getMessage());}
    }
    try{
    conn=DriverManager.getConnection(url,user,password);
    }catch(SQLException e){System.out.println(e.getMessage());}

    return conn;
    } public boolean isAvailableResource(Object resource)
    {
    Connection conn=(Connection)resource;
    try{
    if(!conn.isClosed())
    return true;
    }catch(SQLException e){System.out.println(e.getMessage());}

    return false;
    } public void closeResource(Object resource)
    {
    Connection conn=(Connection)resource;
    try{
    conn.close();
    }
    catch(SQLException e)
    {System.out.println(e.getMessage());}
    }
    }
      

  11.   

    hello Mai_520(网海茫茫,我也忙忙!
    我对基类在创建一个资源对象时使用线程感觉到不理解,就是下面这个方法。
    private void waitForAvailableResource() throws ResourceException
    {
    Thread t=new Thread(this);
    t.start();
    try{
    wait();为什么使用线程来创建一个资源呢?
      

  12.   

    3、我们知道JDBC2.0提供了包含连接池功能的接口,由应用服务器(譬如weblogic\tomcat)来实现。就你所知它比传统的连接池强在那里?这里请加入你实际应用后的体会。最大的好处是不用自己写一个,但移植性就差了一点我不同意这个观点
    现在的容器基本上都是符合规范的,在进行连接池配置的时候只有一些细微的不同,也只是在deploy的时候略有不同,移植性的问题从何而来?
      

  13.   

    ZeroC(笨小孩) 说的对呀,如果容器提供的连接池都符合JDBC2.0的接口约定,好像移植性的问题不存在。需要改配置,不知道麻烦不麻烦。另外笨小孩能不能对比一下各容器厂商的连接池性能?包括这样的连接池能不能实现诸如过时回收这样的功能?顺便也说一下容器管理的连接池比传统连接池强在那里,能不能取代传统连接池?
      

  14.   

    问问大家,在webshpere中如何配置能够连接远程db2数据库的连接池?连接本地的
    DB2数据库都没有问题,就是不知道如何连接远程的数据库,谢谢了!
      

  15.   

    今天,才有时间回贴子。下面是一本书上的例子。虽然比较简单,但还是比较完善的。不懂就问我 :),大家讨论一下!
      /**
       * ThreadPool.java
       */  1: // uses ObjectFIFO   
     
      2:  
     
      3: public class ThreadPool extends Object {  
     
      4:     private ObjectFIFO idleWorkers;  
     
      5:     private ThreadPoolWorker[] workerList;  
     
      6:  
     
      7:     public ThreadPool(int numberOfThreads) {  
     
      8:         // make sure that it’s at least one  
     
      9:         numberOfThreads = Math.max(1, numberOfThreads);  
     
      10:  
     
      11:         idleWorkers = new ObjectFIFO(numberOfThreads);  
     
      12:         workerList = new ThreadPoolWorker[numberOfThreads];  
     
      13:  
     
      14:         for ( int i = 0; i < workerList.length; i++ ) {  
     
      15:             workerList[i] = new ThreadPoolWorker(idleWorkers);  
     
      16:         }  
     
      17:     }  
     
      18:  
     
      19:     public void execute(Runnable target) throws InterruptedException {  
     
      20:         // block (forever) until a worker is available  
     
      21:         ThreadPoolWorker worker = (ThreadPoolWorker) idleWorkers.remove();  
     
      22:         worker.process(target);  
     
      23:     }  
     
      24:  
     
      25:     public void stopRequestIdleWorkers() {  
     
      26:         try {  
     
      27:             Object[] idle = idleWorkers.removeAll();  
     
      28:             for ( int i = 0; i < idle.length; i++ ) {  
     
      29:                 ( (ThreadPoolWorker) idle[i] ).stopRequest();  
     
      30:             }  
     
      31:         } catch ( InterruptedException x ) {  
     
      32:             Thread.currentThread().interrupt(); // re-assert  
     
      33:         }  
     
      34:     }  
     
      35:   
     
      36:     public void stopRequestAllWorkers() {  
     
      37:         // Stop the idle one’s first   
     
      38:         // productive.  
     
      39:         stopRequestIdleWorkers();  
     
      40:  
     
      41:         // give the idle workers a quick chance to die  
     
      42:         try { Thread.sleep(250); } catch ( InterruptedException x ) { }  
     
      43:  
     
      44:         // Step through the list of ALL workers.  
     
      45:         for ( int i = 0; i < workerList.length; i++ ) {  
     
      46:             if ( workerList[i].isAlive() ) {  
     
      47:                 workerList[i].stopRequest();  
     
      48:             }  
     
      49:         }  
     
      50:     }  
     
      51: } 
      
     /**
      * ThreadPoolWorker.java
      */
      
      
      1: // uses class ObjectFIFO 
     
      2:  
     
      3: public class ThreadPoolWorker extends Object {  
     
      4:     private static int nextWorkerID = 0;  
     
      5:  
     
      6:     private ObjectFIFO idleWorkers;  
     
      7:     private int workerID;  
     
      8:     private ObjectFIFO handoffBox;  
     
      9:  
     
      10:     private Thread internalThread;  
     
      11:     private volatile boolean noStopRequested;  
     
      12:  
     
      13:     public ThreadPoolWorker(ObjectFIFO idleWorkers) {  
     
      14:         this.idleWorkers = idleWorkers;  
     
      15:  
     
      16:         workerID = getNextWorkerID();  
     
      17:         handoffBox = new ObjectFIFO(1); // only one slot  
     
      18:  
     
      19:         // just before returning, the thread should be created.  
     
      20:         noStopRequested = true;  
     
      21:  
     
      22:         Runnable r = new Runnable() {  
     
      23:                 public void run() {  
     
      24:                     try {  
     
      25:                         runWork();  
     
      26:                     } catch ( Exception x ) {  
     
      27:                         // in case ANY exception slips through  
     
      28:                         x.printStackTrace();  
     
      29:                     }  
     
      30:                 }  
     
      31:             };  
     
      32:   
     
      33:         internalThread = new Thread(r);  
     
      34:         internalThread.start();  
     
      35:     }  
     
      36:  
     
      37:     public static synchronized int getNextWorkerID() {  
     
      38:         // notice: sync’d at the class level to ensure uniqueness  
     
      39:         int id = nextWorkerID;  
     
      40:         nextWorkerID++;  
     
      41:         return id;  
     
      42:     }  
     
      43:  
     
      44:     public void process(Runnable target) throws InterruptedException {  
     
      45:         handoffBox.add(target);  
     
      46:     }  
     
      47:  
     
      48:     private void runWork() {  
     
      49:         while ( noStopRequested ) {  
     
      50:             try {  
     
      51:                 System.out.println(“workerID=” + workerID +  
     
      52:                         “, ready for work”);  
     
      53:                 // Worker is ready work. This will never block  
     
      54:                 // because the idleWorker FIFO queue has  
     
      55:                 // enough capacity for all the workers.  
     
      56:                 idleWorkers.add(this);  
     
      57:  
     
      58:                 // wait here until the server adds a request  
     
      59:                 Runnable r = (Runnable) handoffBox.remove();  
     
      60:  
     
      61:                 System.out.println(“workerID=” + workerID +  
     
      62:                    “, starting execution of new Runnable: “ + r);  
     
      63:                 runIt(r); // catches all exceptions  
     
      64:             } catch ( InterruptedException x ) {  
     
      65:                 Thread.currentThread().interrupt(); // re-assert  
     
      66:             }  
     
      67:         }  
     
      68:     }  
     
      69:  
     
      70:     private void runIt(Runnable r) {  
     
      71:         try {  
     
      72:             r.run();  
     
      73:         } catch ( Exception runex ) {  
     
      74:             // catch any and all exceptions  
     
      75:             System.err.println(”Uncaught exception fell through from run()”);  
     
      76:             runex.printStackTrace();  
     
      77:         } finally {  
     
      78:             // Clear the interrupted flag (in case it comes back  
     
      79:             // set) so that if the loop goes again, the  
     
      80:             // handoffBox.remove() does not mistakenly  
     
      81:             // throw an InterruptedException.  
     
      82:             Thread.interrupted();  
     
      83:         }  
     
      84:     }  
     
      85:  
     
      86:     public void stopRequest() {  
     
      87:         System.out.println(“workerID=” + workerID +  
     
      88:                 “, stopRequest() received.”);  
     
      89:         noStopRequested = false;  
     
      90:         internalThread.interrupt();  
     
      91:     }  
     
      92:  
     
      93:     public boolean isAlive() {  
     
      94:         return internalThread.isAlive();  
     
      95:     }  
     
      96: } 
     
    这里还欠缺一个ObjectFIFO类,我就不贴了,反正就是一个先进先出队列。不过,也就是通过它来实现一些复杂的功能的。
      

  16.   

    再次声明,这并不是我说的那个实际应用中的Pool,因为涉及知识产权,不便贴出(其实,也是因为太大了,说来话长)。给大家一个忠告:
                   实际应用中的好东西,决不是我辈想的那么简单!千万不要想当然,要努力学习!(呵呵,什么时候我也可以给别人忠告了)
      

  17.   

    import java.io.*;
    import java.sql.*;
    import java.util.*;
    import java.util.Date;/**
     * 数据库连接池
     */
    public class DBConnectionManager implements Serializable
    {
    /**
     * 连接池的实例
     */
       static private DBConnectionManager instance;
       /**
        * 客户端个数
        */
       static private int clients;
       static private String output = "false"; /**
     * 包含驱动程序的向量
     */
       private Vector drivers = new Vector();
       /**
        * 写日志对象
        */
       private PrintWriter log;
       /**
        * 存放各种数据库连接池的哈希表
        */
       private Hashtable pools = new Hashtable(); /**
     * 取得一个数据库连接池的实例
     */
    static synchronized public DBConnectionManager getInstance()
    {
    if (instance == null)
    {
    instance = new DBConnectionManager();
    instance.init();
    }
    clients++;
    return instance;
    } /**
     * 释放一个数据库连接
     */
    public void freeConnection(String name, Connection con)
    {
    DBConnectionPool pool = (DBConnectionPool) pools.get(name);
    if (pool != null)
    {
    pool.freeConnection(con);
    }
    } /**
     * 根据数据库名称取得一个连接
     */
    public Connection getConnection(String name)
    {
    DBConnectionPool pool = (DBConnectionPool) pools.get(name);
    if(pool != null)
    {
    Connection mycn = pool.getConnection();
    return mycn;
    }
    return null;
    } /**
     * 根据数据库名称和延时时间取得一个连接
     */
    public Connection getConnection(String name, long time)
    {
    DBConnectionPool pool = (DBConnectionPool) pools.get(name);
    if (pool != null)
    {
    return pool.getConnection(time);
    }
    return null;
    } /**
     * 释放所有的连接
     */
    public synchronized void release()
    {
    if (--clients != 0)
    {
    return;
    }
    Enumeration allPools = pools.elements();
    while (allPools.hasMoreElements())
    {
    DBConnectionPool pool = (DBConnectionPool) allPools.nextElement();
    pool.release();
    }
    Enumeration allDrivers = drivers.elements();
    while (allDrivers.hasMoreElements())
    {
    Driver driver = (Driver) allDrivers.nextElement();
    try
    {
    DriverManager.deregisterDriver(driver);
    }catch (SQLException e)
    {
    e.printStackTrace();
    }
    }
    } /**
     * 根据配置属性建立数据库连接池
     */
    private void createPools(Properties props)
    {
    Enumeration propNames = props.propertyNames();
    while (propNames.hasMoreElements())
    {
    String name = (String) propNames.nextElement();
    if (name.endsWith(".url"))
    {
    String poolName = name.substring(0, name.lastIndexOf("."));
    String url = props.getProperty(poolName + ".url");
    if (url == null)
    {
    continue;
    }
    String user = props.getProperty(poolName + ".user");
    String password = props.getProperty(poolName + ".password");
    String maxconn = props.getProperty(poolName + ".maxconn", "0");
    int max;
    try
    {
    max = Integer.valueOf(maxconn).intValue();
    }catch (NumberFormatException e)
    {
    max = 50;
    }
    DBConnectionPool pool = new DBConnectionPool(poolName, url, user, password, max);
    pools.put(poolName, pool);
    }
    }
    } /**
     *读取配置文件内容
     */
    private void init()
    {
    //InputStream is = getClass().getResourceAsStream("/db.properties");
    Properties dbProps = new Properties();
    String filename = null;
    try
    {
    String pwd = System.getProperty("pwd");
    if(!pwd.endsWith(File.separator))
    pwd += File.separator;
    filename = pwd + "db.properties";
    File file = new File(filename);
    InputStream is = new FileInputStream(filename);
    dbProps.load(is);
    }catch (Exception e)
    {
    System.err.println("Can not read config file:" + filename);
    return;
    }
    output = dbProps.getProperty("output","false");
    String logFile = dbProps.getProperty("logfile", "DBConnectionManager.log");
    try
    {
    log = new PrintWriter(new FileWriter(logFile, true), true);
    }catch (IOException e)
    {
    System.err.println("can not open log file: " + logFile);
    log = new PrintWriter(System.err);
    }
    loadDrivers(dbProps);
    createPools(dbProps);
    } /**
     * 根据配置属性实例化驱动程序
     */
    private void loadDrivers(Properties props)
    {
    String driverClasses = props.getProperty("drivers");
    StringTokenizer st = new StringTokenizer(driverClasses);
    while (st.hasMoreElements())
    {
    String driverClassName = st.nextToken().trim();
    try
    {
    Driver driver = (Driver)Class.forName(driverClassName).newInstance();
    DriverManager.registerDriver(driver);
    drivers.addElement(driver);
    }catch (Exception e)
    {
    }
    }
    } /**
     * 输出日志
     */
    private void log(String msg)
    {
    if(output.equals("true"))
    log.println(new Date() + ": " + msg);
    } private void log(Throwable e, String msg)
    {
    log.println(new Date() + ": " + msg);
    e.printStackTrace(log);
    } /**
     * 内部连接池类
     */
    class DBConnectionPool
    {
    private int checkedOut;
    private Vector freeConnections = new Vector();
    private int maxConn;
    private String name;
    private String password;
    private String strurl;
    private String user; /**
     * @param name 数据库名
     * @param strurl 数据库URL
     * @param user 用户名
     * @param password 密码
     * @param maxConn 最大连接数
     */
    public DBConnectionPool(String name, String strurl, String user, String password, int maxConn)
    {
    this.name = name;
    this.strurl = strurl;
    this.user = user;
    this.password = password;
    this.maxConn = maxConn;
    } /**
     * 释放连接
     */
    public synchronized void freeConnection(Connection con)
    {
    freeConnections.addElement(con);
    checkedOut--;
    notifyAll();
    } /**
     * 取得一个空闲连接或者新建一个连接
     */
    public synchronized Connection getConnection()
    {
    Connection con = null;
    if(freeConnections.size() > 0)
    {
    con = (Connection) freeConnections.firstElement();
    freeConnections.removeElementAt(0);
    try
    {
    if (con.isClosed())
    {
    con = getConnection();
    }
    }catch (SQLException e)
    {
    e.printStackTrace();
    con = getConnection();
    }
    }else
    {
    if (checkedOut >= maxConn)
    {
    maxConn++;
    }
    con = newConnection();
    if (con != null)
    {
    checkedOut++;
    }
    }
    return con;
    } /**
     * 根据指定延时取得一个连接
     */
    public synchronized Connection getConnection(long timeout)
    {
    long startTime = new Date().getTime();
    Connection con;
    while ((con = getConnection()) == null)
    {
    try
    {
    wait(timeout);
    }catch (InterruptedException e){}
    if ((new Date().getTime() - startTime) >= timeout)
    {
    return null;
    }
    }
    return con;
    } /**
     * 释放所有连接
     */
    public synchronized void release()
    {
    Enumeration allConnections = freeConnections.elements();
    while (allConnections.hasMoreElements())
    {
    Connection con = (Connection) allConnections.nextElement();
    try
    {
    con.close();
    }catch (SQLException e)
    {
    e.printStackTrace();
    }
    }
    freeConnections.removeAllElements();
    checkedOut = 0;
    } /**
     * 建立并取得新的连接
     */
    private Connection newConnection()
    {
    Connection con = null;
    try
    {
    if (user == null)
    {
    con = DriverManager.getConnection(strurl);
    }else
    {
    con = DriverManager.getConnection(strurl, user, password);
    }
    }catch (SQLException e)
    {
    e.printStackTrace();
    return null;
    }
    return con;
    }
    }
    }
    ///:~
    配置文件例子:
    oracle.drivers=
    oracle.url=
    oracle.user=
    oracle.password=
    oracle.maxconn=
      

  18.   

    就算都遵守JDBC2.0规范也会有所不同因为他们的实现不一样,可能是规范不完善,可能是BUG,也可能是说不上是BUG的其他小细节上的问题比如,Servlet引擎都符合Servlet规范,为什么中文问题在Tomcat和Resin中表现不一样?另外,应用服务器都遵守J2EE规范,但是不同的厂商会提供一些自己的功能,这需要你的开发人员有足够的水平,不然他们可能会在需要移植的项目中用到厂商独特的功能
      

  19.   

    DBMS都符合SQL标准,数据库驱动程序又符合JDBC规范,为什么大家讨论数据库问题的时候要指出所用的数据库系统和驱动程序?部署时的差别也是影响移植性的重要因素,开发一个大一点的系统会用到很多东西,如果它们在不同的系统之间部署不一样,那么整个系统的部署就会很麻烦当然象数据源这样的实现不会有太多的差异,我认为还是用容器提供的比较好。但总应该知道移植到另一个系统上是游可能有不一样的表现的由不同的实现之间的细微差别导致的移植性错误往往是很难查找的,只有水平足够好开发人员的才能开发出移植性好的系统。移植性的问题应该尽量在开发时就意识到,而不是部署到另一个系统上出现毛病以后再来修补
      

  20.   

    哇塞,2个代码贴出来了。够看一壶的,看完交流。 AYellow(北斗猪) 也不无道理,继续讨论。
      

  21.   

    private void waitForAvailableResource() throws ResourceException
    {
    Thread t=new Thread(this);
    t.start();
    try{
    wait();用一个新的线程去创建一个数据库连接,在run方法调用createResource(),
    因为建立连接通常比较毫时,所以用一个新线程去做这些事,从而避免请求线程没有调用wait方法就被阻塞,这是不安全的。可能我没说太清楚:)
      

  22.   

    有个问题实在值的一问。象 oicu(阿猫)贴的那个连接池也差不多是正在用的,它只在释放和取连接的时候synchronized了一下。那么你怎么保证是一个线程来取数据呢,这时候怎么保证同步呢????
    那么是不是Mai_520的例子那样不管是不是线程,到我这里都给你建立一个线程更合理呢。如果取数据的就是线程会不会出问题呢???我可能没说清楚。我对线程不是很精通。
      

  23.   

    我觉得为了保证线程安全,又不要使用像synchronized这样的重量级的线程同步方法。最好的解决方案就是利用数据结构了,那就是用Block队列(Queue)来保证线程安全了。
      

  24.   

    Norwaywoods() 的想法很新颖。留个qq先Block队列(Queue)?先进先出队列?里面保存什么东东?
      

  25.   

    其实就上面的问题我在补充一下,每个servlet在提供服务时实际上是启用一个线程。那么这个线程在提取数据库连接时。由于synchronized了所以是线程安全的。确保了池中数据同步。那么Mai_520提供的池里在创建线程是不是没有意义。
    反过来说,如果不是servlet这样启用线程来拿连接。又有什么同步问题呢?
    没有线程,就没有同步。我的理解对么,请指正。
      

  26.   

    其实,数据库连接池的处理,已经有专门的一个OpenSource的java工程,叫做poolman,做的很好,我在的公司里,有很多项目都是用它做数据库连接,很稳定。这个东东,做成了jdbc驱动程序的形式,用起来很简单,在配置文件中做一下简单的配置,之后,就可以象使用jdbc驱动程序一样使用。如果你现在需要用到连接池,那么它是最好的选择,免费,不涉及知识产权;
    如果想学习连接池,也可以看看它的源代码,写得很精彩,看了后,保证会受益匪浅;下面是一个简单得例子(只是一个片断):
    ......
    try 
    {
      // load the PoolMan JDBC Driver
      Class.forName("com.codestudio.sql.PoolMan").newInstance();

    catch (Exception ex) 
    {
      System.out.println("Could Not Find the PoolMan Driver. " +
                                   "Is poolman.jar in your CLASSPATH?");
      System.exit(0);
    }
    Connection con = DriverManager.getConnection("jdbc:poolman");
    ......
      

  27.   

    有没有用C++写的对Informix数据库的数据库连接池?
      

  28.   

    GJA106(中文字符)别晕呀,我在晕晕。需要你的清醒:)
      

  29.   

    oicu(阿猫)的代码不错,不过这个pool好像少了超时断开这个对健壮性有很大影响的设计
      

  30.   

    Mai_520(网海茫茫,我也忙忙!)
    你的mai.database.pool.ResourceException;这个在哪阿muymuy(muy) 那个poolman从哪可以下载阿,在网上没有找到阿。
      

  31.   

    Norwaywoods() 你那个ObjectFIFO类还是给出来的好,不然如何去使用阿。
      

  32.   

    你要的ObjectFIFO。
    摘自:
    Java Thread Programming  
    Paul Hyde 
    Copyright &copy; 1999 Sams Publishing 
     1: public class ObjectFIFO extends Object {  
     
        2:     private Object[] queue;  
     
        3:     private int capacity;  
     
        4:     private int size;  
     
        5:     private int head;  
     
        6:     private int tail;  
     
        7:   
     
        8:     public ObjectFIFO(int cap) {  
     
        9:         capacity = ( cap > 0 ) ? cap : 1; // at least 1  
     
      10:         queue = new Object[capacity];  
     
      11:         head = 0;  
     
      12:         tail = 0;  
     
      13:         size = 0;  
     
      14:     }  
     
      15:   
     
      16:     public int getCapacity() {  
     
      17:         return capacity;  
     
      18:     }  
     
      19:   
     
      20:     public synchronized int getSize() {  
     
      21:         return size;  
     
      22:     }  
     
      23:   
     
      24:     public synchronized boolean isEmpty() {  
     
      25:         return ( size == 0 );  
     
      26:     }  
     
      27:   
     
      28:     public synchronized boolean isFull() {  
     
      29:         return ( size == capacity );  
     
      30:     }  
     
      31:   
     
      32:     public synchronized void add(Object obj)   
     
      33:             throws InterruptedException {  
     
      34:   
     
      35:         waitWhileFull();  
     
      36:   
     
      37:         queue[head] = obj;  
     
      38:         head = ( head + 1 ) % capacity;  
     
      39:         size++;  
     
      40:   
     
      41:         notifyAll(); // let any waiting threads know about change  
     
      42:     }  
     
      43:   
     
      44:     public synchronized void addEach(Object[] list)   
     
      45:             throws InterruptedException {  
     
      46:   
     
      47:         //  
     
      48:         // You might want to code a more efficient   
     
      49:         // implementation here ... (see ByteFIFO.java)  
     
      50:         //  
     
      51:   
     
      52:         for ( int i = 0; i < list.length; i++ ) {  
     
      53:             add(list[i]);  
     
      54:         }  
     
      55:     }  
     
      56:   
     
      57:     public synchronized Object remove()   
     
      58:             throws InterruptedException {  
     
      59:   
     
      60:         waitWhileEmpty();  
     
      61:   
     
      62:         Object obj = queue[tail];  
     
      63:   
     
      64:         // don’t block GC by keeping unnecessary reference  
     
      65:         queue[tail] = null;   
     
      66:   
     
      67:         tail = ( tail + 1 ) % capacity;  
     
      68:         size—;  
     
      69:   
     
      70:         notifyAll(); // let any waiting threads know about change  
     
      71:   
     
      72:         return obj;  
     
      73:     }  
     
      74:   
     
      75:     public synchronized Object[] removeAll()   
     
      76:             throws InterruptedException {  
     
      77:   
     
      78:         //  
     
      79:         // You might want to code a more efficient   
     
      80:         // implementation here ... (see ByteFIFO.java)  
     
      81:         //  
     
      82:   
     
      83:         Object[] list = new Object[size]; // use the current size  
     
      84:   
     
      85:         for ( int i = 0; i < list.length; i++ ) {  
     
      86:             list[i] = remove();  
     
      87:         }  
     
      88:   
     
      89:         // if FIFO was empty, a zero-length array is returned  
     
      90:         return list;   
     
      91:     }  
     
      92:   
     
      93:     public synchronized Object[] removeAtLeastOne()   
     
      94:             throws InterruptedException {  
     
      95:   
     
      96:         waitWhileEmpty(); // wait for at least one to be in FIFO  
     
      97:         return removeAll();  
     
      98:     }  
     
      99:   
     
      
     Listing 18.4  Continued   
     
      
     100:     public synchronized boolean waitUntilEmpty(long msTimeout)   
     
      101:             throws InterruptedException {  
     
      102:   
     
      103:         if ( msTimeout == 0L ) {  
     
      104:             waitUntilEmpty();  // use other method  
     
      105:             return true;  
     
      106:         }  
     
      107:   
     
      108:         // wait only for the specified amount of time  
     
      109:         long endTime = System.currentTimeMillis() + msTimeout;  
     
      110:         long msRemaining = msTimeout;  
     
      111:   
     
      112:         while ( !isEmpty() && ( msRemaining > 0L ) ) {  
     
      113:             wait(msRemaining);  
     
      114:             msRemaining = endTime - System.currentTimeMillis();  
     
      115:         }  
     
      116:   
     
      117:         // May have timed out, or may have met condition,   
     
      118:         // calc return value.  
     
      119:         return isEmpty();  
     
      120:     }  
     
      121:   
     
      122:     public synchronized void waitUntilEmpty()   
     
      123:             throws InterruptedException {  
     
      124:   
     
      125:         while ( !isEmpty() ) {  
     
      126:             wait();  
     
      127:         }  
     
      128:     }  
     
      129:   
     
      130:     public synchronized void waitWhileEmpty()   
     
      131:             throws InterruptedException {  
     
      132:   
     
      133:         while ( isEmpty() ) {  
     
      134:             wait();  
     
      135:         }  
     
      136:     }  
     
      137:   
     
      138:     public synchronized void waitUntilFull()   
     
      139:             throws InterruptedException {  
     
      140:   
     
      141:         while ( !isFull() ) {  
     
      142:             wait();  
     
      143:         }  
     
      144:     }  
     
      145:   
     
      146:     public synchronized void waitWhileFull()   
     
      147:             throws InterruptedException {  
     
      148:   
     
      149:         while ( isFull() ) {  
     
      150:             wait();  
     
      151:         }  
     
      152:     }  
     
      153: } 
     
      

  33.   

    先谢过Norwaywoods() 了回去研究代码喽 :)