连接池的结构类图已经在上面详细给出,现在我们来分析一个源码:
- public GenericPool(PoolHelper helper, int minSize, int maxSize,
- long lifeTime, long sleepTime, long maxLifeTime) {
- //连接工厂
- this.threadFactory = null;
- //生命周期
- this.lifeTime = lifeTime;
- //最大生命周期
- this.maxLifeTime = maxLifeTime;
- //最小容量
- this.minSize = minSize;
- //最大容量
- this.maxSize = maxSize;
- //容器中包含对象的生产工厂
- this.poolHelper = helper;
- this.sleepTime = sleepTime;
- this.checkLevelObject = 0;
- this.deadLockMaxWait = DEFAULT_DEADLOCKMAXWAIT;
- this.deadLockRetryWait = DEFAULT_DEADLOCKRETRYWAIT;
- }
- public synchronized void start() {
- //已经在使用的对象队列
- locked = new Hashtable(); // create locked objects pool
- //当前可用的对象的队列
- unlocked = new Hashtable(); // create unlocked objects pool
- hitList = new Vector();
- count = 0; // 0 element to start
- gc = false; // do not actions concerning garbage collector
- //记录起始时间,开始计算对象生成的时间;
- long now = System.currentTimeMillis(); // current time
- // to obtain to the beginning minSize objects in the pool
- //生成最小的对象个数
- for (int i = 0; i < minSize; i++) { // count have to be equal to minSize
- try {
- //抽象工厂模式,自定义工厂生产自定义的产品;把具体的工厂和产品解耦;
- GenerationObject genObject = poolHelper.create();
- //把数据和时间都都存储起来
- unlocked.put(genObject, new Long(now));
- // put it in the unlocked pool
- } catch (Exception e) {
- log.error("Error Exception in GenericPool:start " + e);
- }
- //把当前连接池所有对象的个数增加;
- ++count; // there is one more element in the pool
- }
- // keeper removes dead or useless objects
- if (threadFactory != null) {
- try {
- this.poolKeeper = new PoolKeeper(sleepTime, this);
- this.keeper = threadFactory.getThread(poolKeeper);
- } catch (Exception e) {
- throw new IllegalStateException(e.getMessage());
- }
- } else {
- // keep a handle to the poolkeeper so we can destroy it later
- this.poolKeeper = new PoolKeeper(sleepTime, this);
- this.keeper = new Thread(poolKeeper);
- }
- //启动一个连接池维护线程;
- keeper.start();
- // start the thread to verify element in the pool(unlocked)
- log.debug("GenericPool:start pool started");
- }
- public GenerationObject create() throws SQLException {
- return create(getUser(), getPassword());
- }
- public GenerationObject create(String _user, String _password)
- throws SQLException {
- log.debug(
- "StandardPoolDataSource:create create a connection for the pool");
- GenerationObject genObject;
- PooledConnection pooledCon = cpds.getPooledConnection(_user, _password);
- // get the pooled connection
- //生产的连接绑定到了自身,方便回笼;
- pooledCon.addConnectionEventListener(this);
- // add it to the event listener
- log.debug("StandardPoolDataSource:create create a object for the pool");
- genObject =
- new GenerationObject(
- pooledCon,
- pool.getGeneration(),
- _user,
- _password);
- return genObject; // return a connection
- }
下面介绍一下对象的取出和回笼;
- public Object checkOut(String user, String password) throws Exception {
- log.debug("GenericPool:checkOut an object");
- //拿到当前的时间;
- long now = System.currentTimeMillis(); // current time to compare
- GenerationObject o;
- Enumeration e;
- Object realObject;
- log.debug("GenericPool:checkOut UnlockedObjectCount="
- + getUnlockedObjectCount());
- log.debug("GenericPool:checkOut LockedObjectCount="
- + getLockedObjectCount());
- log
- .debug("GenericPool:checkOut count=" + count + " maxSize="
- + maxSize);
- //如果当前存在可用对象
- if (getUnlockedObjectCount() > 0) {
- // if there are objects in the unlocked pool
- if ((checkLevelObject == 3) || (checkLevelObject == 4)) { // need
- // to
- // verify
- // all
- // the
- // objects
- //遍历这些对象
- e = unlocked.keys();
- while (e.hasMoreElements()) {
- o = (GenerationObject) e.nextElement();
- //存在可用的对象
- realObject = o.getObj(); // take the current object
- // first, verify if the object is not dead (lifetime)
- //如果当前元素过期的话
- Long life = (Long) unlocked.get(o);
- if (life == null
- || (now - life.longValue()) > lifeTime
- || (maxLifeTime > 0 && (now - o.getCreated()) > maxLifeTime)) {
- // object has expired
- log.debug("GenericPool:checkOut an object has expired");
- //从可用的队列中移除
- removeUnlockedObject(o);
- // minimumObject(user, password);
- // build object in the pool if it is lesser than minSize
- } else {
- log
- .debug("GenericPool:checkOut check the owner of the connection");
- //检查拥有者
- if (checkOwner(o, user, password)) {
- if (((checkLevelObject == 3) && !poolHelper
- .checkThisObject(realObject))
- || ((checkLevelObject == 4) && !poolHelper
- .testThisObject(realObject))) {
- log
- .debug("GenericPool:checkOut remove object checkLevelObject="
- + checkLevelObject);
- //不合法移除;
- removeUnlockedObject(o);
- // minimumObject(user, password);
- // build object in the pool if it is lesser than
- // minSize
- }
- }
- }
- }
- }
- }
- int currentWait = 0;
Object obj = getFromPool(user, password);
while ((obj == null) && (currentWait < getDeadLockMaxWait())) {
log.info("GenericPool:checkOut waiting for an object :"
+ this.poolHelper.toString());
try {
synchronized (this) {
//当没有对象的时候,等待若干时间
wait(getDeadLockRetryWait());
}
} catch (InterruptedException excp) {
log
.error("GenericPool:checkOut ERROR Failed while waiting for an object: "
+ excp);
}
currentWait += getDeadLockRetryWait();
//在重新尝试从池中取出可用对象;
obj = getFromPool(user, password);
}
if (obj == null)
throw new Exception(
"GenericPool:checkOut ERROR impossible to obtain a new object from the pool");
return obj;
}
- private Object getFromPool(String user, String password) throws Exception {
- long now = System.currentTimeMillis(); // current time to compare
- if (getUnlockedObjectCount() > 0) {
- // now, we have to return an object to the user
- GenerationObject o = null;
- Object realObject = null;
- Long life = null;
- Enumeration e = unlocked.keys(); // then take them
- while (e.hasMoreElements()) { // for each objects ...
- synchronized (this) {
- // Ensure that there are object in the unlocked
- // collection
- if (getUnlockedObjectCount() == 0)
- break;
- o = (GenerationObject) e.nextElement();
- life = (Long) unlocked.get(o);
- if (life == null) {
- // Fix for #303462; note that this fixes the problem, but Enumeration's on Hashtable's
- // are by definition somewhat unpredictable; a more robust fix may be in order
- log.debug("GenericPool:getFromPool fix for #303462 encountered");
- continue;
- }
- //从可用对象的队列中移除
- unlocked.remove(o);
- // In any case the object will be removed.
- // Prevents others accessing the object while we are
- // not synchronized.
- //返回其真实对象;
- realObject = o.getObj();
- }
- // Verify that the life object is valid
- if (life == null)
- break;
- // first, verify if the object is not dead (lifetime)
- if (life == null
- || (now - life.longValue()) > lifeTime
- || (maxLifeTime > 0 && (now - o.getCreated()) > maxLifeTime)) {
- // object has expired
- log.debug("GenericPool:getFromPool an object has expired");
- removeUnlockedObject(o);
- } else {
- log
- .debug("GenericPool:getFromPool check the owner of the connection");
- if (checkOwner(o, user, password)) {
- log.debug("GenericPool:getFromPool owner is verified");
- // second, verification of the object if needed
- if ((checkLevelObject == 0)
- || ((checkLevelObject == 1) && poolHelper
- .checkThisObject(realObject))
- || ((checkLevelObject == 2) && poolHelper
- .testThisObject(realObject))) {
- locked.put(o, new Long(now));
- // put it in the locked pool
- log
- .debug("GenericPool:getFromPool return an object (after verification if needed)");
- return (o.getObj()); // return this element
- } else { // object failed validation
- // System.out.println("removeUnlockedObject="+realObject);
- log
- .debug("GenericPool:getFromPool kill an object from the pool");
- removeUnlockedObject(o);
- }
- } else
- log.debug("GenericPool:getFromPool owner is FALSE");
- }
- }
- } // if getUnlockedObjectCount() > 0
- // if no objects available, create a new one
- boolean create = false;
- //若是已有对象总和没有超过最大容量,可以自己新建对象
- synchronized (this) {
- if (count < maxSize) {
- create = true;
- count++; // assume we can create a connection.
- }
- }
- if (create) {
- // System.out.println("on doit creer une connection");
- // if number of pooled object is < max size of the pool
- log
- .debug("GenericPool:getFromPool no objects available, create a new one");
- try {
- // System.out.println("on doit creer une connection CREATE");
- GenerationObject genObject = poolHelper.create(user, password);
- // System.out.println("nouvel objet="+genObject.getObj());
- // System.out.println("on doit creer une connection PUT");
- locked.put(genObject, new Long(now));
- // put it in the locked pool
- return (genObject.getObj()); // and return this element
- } catch (Exception excp) {
- synchronized (this) {
- count--; // our assumption failed. rollback.
- }
- log
- .error("GenericPool:getFromPool Error Exception in GenericPool:getFromPool");
- // cney: rethrow exception thrown by create
- throw excp;
- }
- }
- //否则返回空,继续等待
- return null;
- }
- public synchronized void checkIn(Object o) {
- log.debug("GenericPool:checkIn return an object to the pool");
- for (Enumeration enumeration = locked.keys(); enumeration.hasMoreElements();) { // for
- // each
- // object
- // of
- GenerationObject obj = (GenerationObject) enumeration.nextElement();
- // the locked pool
- if (obj.getObj().equals(o)) {
- //从锁定的对象从锁定队列中移入可用队列中
- locked.remove(obj); // remove the object from the locked pool
- unlocked.put(obj, new Long(System.currentTimeMillis()));
- // we have to verify if the generation of the object is still
- // valid
- int genObj = obj.getGeneration(); // get the generation number
- // if the generation number of the object is not valid, test the
- // object
- if (generation > genObj) {
- if (!poolHelper.checkThisObject(obj.getObj()))
- // if the object is not valid
- removeUnlockedObject(obj);
- }
- //唤醒线程
- notifyAll();
- }
- }
- public class PoolKeeper implements Runnable {
- private long sleepTime; // timeout between 2 clean up
- private GenericPool pool; // the pool to clean up
- private boolean running = true;
- /**
- * constructor, called by GenericPool (any kind of object)
- */
- public PoolKeeper(long sleepTime, GenericPool pool) {
- this.sleepTime = sleepTime;
- this.pool = pool;
- }
- public void stop() {
- synchronized (this ) {
- running = false;
- }
- }
- /**
- * run method. allows to clean up the pool
- */
- public void run() {
- while (running && !Thread.interrupted()) {
- try {
- synchronized (this) {
- wait(this.sleepTime); // wait for timeout ms before attack
- }
- } catch (InterruptedException e) {
- break;
- }
- //特定时间间隔的清扫连接池;
- this.pool.cleanUp(); // clean up the Pool and reallocate objects
- }
- // release the pool.
- this.pool = null;
- }
- long now = System.currentTimeMillis(); // current time
- synchronized (this) {
- for (Enumeration enumeration = unlocked.keys(); enumeration.hasMoreElements();) { // for
- // each
- // object
- // of
- // the
- GenerationObject o = (GenerationObject) enumeration.nextElement();
- // unlocked pool
- Long lasttouch = (Long) unlocked.get(o);
- // birth day of the pool
- if (lasttouch == null
- || (now - lasttouch.longValue()) > lifeTime
- || (maxLifeTime > 0 && (now - o.getCreated()) > maxLifeTime)) {
- log.debug("GenericPool:cleanUp clean up the pool");
- removeUnlockedObject(o);
- }
- }
- }
- public void expire(Object o) {
- log.debug(
- "StandardPoolDataSource:expire expire a connection, remove from the pool");
- if (o == null)
- return;
- try {
- PooledConnection pooledCon = (PooledConnection) o;
- pooledCon.close(); // call close() of PooledConnection
- pooledCon.removeConnectionEventListener(this);
- log.debug("StandardPoolDataSource:expire close the connection");
- } catch (java.sql.SQLException e) {
- log.error(
- "StandardPoolDataSource:expire Error java.sql.SQLException in StandardPoolDataSource:expire");
- }
- }
- public Connection getConnection(String _user, String _password)
- throws SQLException {
- log.debug("StandardPoolDataSource:getConnection");
- Connection ret = null;
- PooledConnection con = null;
- synchronized (this) {
- if (!onOff) {
- log.debug(
- "StandardPoolDataSource:getConnection must configure the pool...");
- pool.start(); // the pool starts now
- onOff = true; // and is initialized
- log.debug(
- "StandardPoolDataSource:getConnection pool config : /n"
- + pool.toString());
- }
- }
- try {
- try {
- log.debug(
- "StandardPoolDataSource:getConnection Try to give a "
- + "connection (checkOut)");
- //从连接池中取得PooledConnection;
- con = (PooledConnection) pool.checkOut(_user, _password);
- // get a connection from the pool
- log.debug(
- "StandardPoolDataSource:getConnection checkOut return"
- + "a new connection");
- } catch (Exception e) {
- e.printStackTrace();
- log.debug(
- "StandardPoolDataSource:getConnection SQLException in StandardPoolDataSource:getConnection"
- + e);
- throw new SQLException(
- "SQLException in StandardPoolDataSource:getConnection no connection available "
- + e);
- }
- //取得物理连接
- ret = con.getConnection();
- } catch (Exception e) {
- log.debug("StandardPoolDataSource:getConnection exception" + e);
- e.printStackTrace();
- SQLException sqle =
- new SQLException(
- "SQLException in StandardPoolDataSource:getConnection exception: "
- + e);
- if (e instanceof SQLException)
- sqle.setNextException((SQLException) e);
- if (con != null) {
- pool.checkIn(con);
- }
- throw sqle;
- }
- log.debug("StandardPoolDataSource:getConnection return a connection");
- return ret;
- }
(1)工厂和监听者集为一身,在场景,如产品还要工厂进行同意的售后服务等等;
(2)线程扫描,时间间隔等等;