这是一段有关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);
} }
}
理论问题:,对象的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);
} }
}
我们不考虑上面的问题,说说你的代码。其实同步pool,不是说挂起pool锁起pool之类的,而是给pool加锁,这样同时只能有一个线程访问它
而其他试图访问它的线程就会处于等待状态,直到被notifywhile((ldapconnection = getConnFromPool()) == null)
synchronized(pool)
//这里的意思不是让pool挂起,是在池里面查看是否有连接对象可以生成,循环里面是已经发现连接全部被使用没有可用的了,那么这时候访问getConnection的线程将同步,直到有其他线程使用的连接释放了被notify这些在等待的线程,那么他们将跳出这个while循环,得到连接。
{
try
{
pool.wait(i);
}
catch(InterruptedException _ex) { }
}
return ldapconnection;
}
wait() 是在等待
直到notify()或notifyAll()
所以我也觉得同步这个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的线程同步
这个理解对否,敬候大虾的回复
而pool.wait(i)是将访问getConnection的线程同步----------
我上面说了那么多就是你这2句话。。
这个理解是否对呢?