这是一段有关LDAP连接池的代码,其实什么连接我门不用关注是什么连接,只要关心这是一个连接池的实现即可,我的问题是这段代码中有关wait与notify的部分
理论问题:,对象的wait到底是挂起什么?
:请重点看getConnection()与closeConnection()方法
package netscape.ldap.util;import java.io.PrintStream;
import java.util.Date;
import java.util.Vector;
import netscape.ldap.LDAPConnection;
import netscape.ldap.LDAPException;public class ConnectionPool
{
    /**
     *  描述一个LDAP连接对象是否可用的内部类
     *
     */
    class LDAPConnectionObject
    {        private LDAPConnection ld;
        private boolean inUse;        LDAPConnection getLDAPConn()
        {
            return ld;
        }        boolean isAvailable()
        {
            return inUse ^ true;
        }        void setInUse(boolean flag)
        {
            inUse = flag;
        }        void setLDAPConn(LDAPConnection ldapconnection)
        {
            ld = ldapconnection;
        }        public String toString()
        {
            return "LDAPConnection=" + ld + ",inUse=" + inUse;
        }        LDAPConnectionObject()
        {
        }
    }
    private int poolSize;
    private int poolMax;
    private String host;
    private int port;
    private String authdn;
    private String authpw;
    private LDAPConnection ldc;    /**
     * Vector 来存放连接对象,是实际的连接池
     */
    private Vector pool;
    private boolean debugMode;     
   /**
    *  当关闭一个连接时,就让一个等待连接的进程获取这个可用连接
    **/
    public synchronized void close(LDAPConnection ldapconnection)
    {
        int i = find(ldapconnection);
        if(i != -1)
        {
            LDAPConnectionObject ldapconnectionobject = (LDAPConnectionObject)pool.elementAt(i);
            ldapconnectionobject.setInUse(false);
            /**
             * 通知所有的已挂起的pool对象? 
             */
            synchronized(pool)
            {
                pool.notifyAll();
            }
        }
    }    private void createPool()
        throws LDAPException
    {
        if(poolSize <= 0)
            throw new LDAPException("ConnectionPoolSize invalid");
        if(poolMax < poolSize)
        {
            debug("ConnectionPoolMax is invalid, set to " + poolSize);
            poolMax = poolSize;
        }
        debug("****Initializing LDAP Pool****");
        debug("LDAP host = " + host + " on port " + port);
        debug("Number of connections=" + poolSize);
        debug("Maximum number of connections=" + poolMax);
        debug("******");
        pool = new Vector();
        setUpPool(poolSize);
    }     
    
 
     
    protected synchronized LDAPConnection getConnFromPool()
    {
        LDAPConnection ldapconnection = null;
        LDAPConnectionObject ldapconnectionobject = null;
        int i = pool.size();
        for(int j = 0; j < i; j++)
        {
            LDAPConnectionObject ldapconnectionobject1 = (LDAPConnectionObject)pool.elementAt(j);
            if(!ldapconnectionobject1.isAvailable())
                continue;
            ldapconnectionobject = ldapconnectionobject1;
            break;
        }        if(ldapconnectionobject == null)
            if(poolMax < 0 || poolMax > 0 && i < poolMax)
            {
                int k = addConnection();
                if(k >= 0)
                    ldapconnectionobject = (LDAPConnectionObject)pool.elementAt(k);
            } else
            {
                debug("All pool connections in use");
            }
        if(ldapconnectionobject != null)
        {
            ldapconnectionobject.setInUse(true);
            ldapconnection = ldapconnectionobject.getLDAPConn();
        }
        return ldapconnection;
    }
    
    /**
     *  获取连接时,若连接池已满,将连接池挂起
     */
    public LDAPConnection getConnection()
    {
        LDAPConnection ldapconnection;
        while((ldapconnection = getConnFromPool()) == null) 
            /**
             * 这是我最不能理解的一个地方,将pool作为同步锁,,然后又将pool挂起?
             * 如果连接池已满,现在有10个等待连接的进程,那么pool启不要挂起10次
             * 如果连接池已满,现在有n个等待连接的进程,那么pool启不要挂起n次?
             * 这个意义何在呢?
             * 网上查拉一些文档,也回去看拉一些书,发现有关wait的例子都是有关线程的
             * (即调用wait的对象都是继承Thread的),我当然知道wait是Object的方法
             * 问题是:这种非继承Thread的对象调用wait方法的范例,我还是第一次见
             * 继承Thread的对象调用wait时,意思是指挂起这个进程,
             * 那么非继承Thread的对象调用wait方法时,挂起的是谁呢?这个对象?
             * 对象挂起又有什么意义呢?如果是挂起线程,是挂起哪一个呢?当前线程吗?
             * 回到连接池本身这个业务上来,当某个用户从连接池获取的连接为null时,
             * 那么他只能等待,直到连接池中出现一个空闲连接为止
             * 很显然,下面这段代码就是实现这个功能,可是我实在是不明白,这样就能实现吗?
             * 请有识大虾解惑之,不胜感激
             */
            synchronized(pool)
            {
                try
                {
                     pool.wait(i);
                }
                catch(InterruptedException _ex) { }
            }
        return ldapconnection;
    }         private synchronized void setUpPool(int i)
        throws LDAPException
    {
        LDAPConnectionObject ldapconnectionobject;
        for(; pool.size() < i; pool.addElement(ldapconnectionobject))
        {
            ldapconnectionobject = new LDAPConnectionObject();
            LDAPConnection ldapconnection = ldc == null ? new LDAPConnection() : (LDAPConnection)ldc.clone();
            ldapconnectionobject.setLDAPConn(ldapconnection);
            try
            {
                if(ldapconnection.isConnected())
                    ldapconnection.reconnect();
                else
                    ldapconnection.connect(host, port, authdn, authpw);
            }
            catch(LDAPException ldapexception)
            {
                debug("Creating pool:" + ldapexception.toString());
                debug("aborting....");
                throw ldapexception;
            }
            ldapconnectionobject.setInUse(false);
        }    }
}

解决方案 »

  1.   

    其实我很奇怪,pool是Vector的对象,而Vector本身是同步,访问它肯定已经是同步的了。
    我们不考虑上面的问题,说说你的代码。其实同步pool,不是说挂起pool锁起pool之类的,而是给pool加锁,这样同时只能有一个线程访问它
    而其他试图访问它的线程就会处于等待状态,直到被notifywhile((ldapconnection = getConnFromPool()) == null) 
              synchronized(pool)
    //这里的意思不是让pool挂起,是在池里面查看是否有连接对象可以生成,循环里面是已经发现连接全部被使用没有可用的了,那么这时候访问getConnection的线程将同步,直到有其他线程使用的连接释放了被notify这些在等待的线程,那么他们将跳出这个while循环,得到连接。
                {
                    try
                    {
                         pool.wait(i);
                    }
                    catch(InterruptedException _ex) { }
                }
            return ldapconnection;
        }
      

  2.   

    应该是给它的对象加锁
    wait() 是在等待 
    直到notify()或notifyAll()
      

  3.   

    1)这个代码是sun的代码,我反编译的,说实话(我是否侵权呢?哈),为什么用Vector我也怀疑,我当时就问过其他人,最后的结论竟然是这是j2se1.2之前的代码,即那时还没有ArrayList呢?(也不知对否);
    所以我也觉得同步这个pool(Vector对象)也是多余的,因为他的方法本身就是同步
    2)至于"是在池里面查看是否有连接对象可以生成,循环里面是已经发现连接全部被使用没有可用的了,那么这时候访问getConnection的线程将同步,直到有其他线程使用的连接释放了被notify这些在等待的线程,那么他们将跳出这个while循环,得到连接",这是代码的目的,我基本上也推得出来,问题是何必要
    synchronized(pool)
                    try
                    {
                         pool.wait(i);
                    }
                    catch(InterruptedException _ex) { }
                }
    我不作这个同步,就让循环空转不行吗?(这应该不行,因为close也被synchronized)
    但是
    synchronized(this)
                    try
                    {
                          wait(i);
                    }
                    catch(InterruptedException _ex) { }
                }这总是可以,这至少更像"将当前访问getConnection的线程将同步"
    close代码里也改为
    synchronized(this)
                    try
                    {
                          notify.all();
                    }
                    catch(InterruptedException _ex) { }
                }
    这至少看起来更好董一点吗?
    或者连this都可不用,任何一个对象都是可以的,即
    synchronized(anyObject)
                    try
                    {
                          anyObject.wait(i);
                    }
                    catch(InterruptedException _ex) { }
                }
    只要看到anyObject.wait(),如果anyObject不是线程对象(即没有继承Thread),它就一定是同步访问调用anyObject.wait(i);的方法的线程?或者用您的话说就是"访问getConnection的线程将同步"小结:
    如果pool是个ArrayList对象,则
      synchronized(pool)
                    try
                    {
                         pool.wait(i);
                    }
                    catch(InterruptedException _ex) { }
                }
    是唯一选择,因为实际上他实现两个功能:
     synchronized(pool)是锁住pool,即是将pool的每个方法同步
     而pool.wait(i)是将访问getConnection的线程同步
    这个理解对否,敬候大虾的回复
      

  4.   

    synchronized(pool)是锁住pool,即是将pool的每个方法同步
     而pool.wait(i)是将访问getConnection的线程同步----------
    我上面说了那么多就是你这2句话。。
      

  5.   

    只要看到anyObject.wait(),如果anyObject不是线程对象(即没有继承Thread),它就一定是挂起访问调用anyObject.wait(i)的方法的线程? 是线程对象,就是挂起该线程对象
    这个理解是否对呢?