数据源
入口类:ComboPooledDataSource
getConnection方法在AbstractPoolBackedDataSource类中实现。
获取连接
触发机制:
应用主动调用。
调用过程:
1、 AbstractPoolBackedDataSource类getConnection方法 public Connection getConnection() throwsSQLException {
PooledConnectionpc =
getPoolManager().getPool().checkoutPooledConnection();
returnpc.getConnection(); }
接是newProxyConnection,不是物理连接得到连。
说明:
PooledConnection
包名是javax.sql,是sun针对连接池的接口,它本身包含connection,和这个connection相关的所有statement,result,一个checkout的connection所做的所有数据库操作,都被pooledconnection所管理。
c3p0默认的实现是NewPooledConnection
Connection,Statement,Result
操作数据库相关接口,在c3p0中对应于NewProxyConnection,NewProxyStatement,NewProxyResultSet,这些东西统一被PooledConnection管理。
2、 C3P0PooledConnectionPool类
publicPooledConnectioncheckoutPooledConnection()
return ((PooledConnection)this.rp.checkoutResource(this.checkoutTimeout));
3、 BasicResourcePool类
public Object checkoutResource(long timeout)
1) 关键步骤代码:Object resc = prelimCheckoutResource(timeout);
查看池中是否有未使用的connection,有就返回(还要判断是否空闲、是否过期);没有,如果没有达到最大数,就生成一个,或者就等待。
2) 关键步骤代码:
booleanrefurb = attemptRefurbishResourceOnCheckout(resc);
得到连接后,检测连接的可用性。
3) 连接可用,接着判断连接是否处于管理中,不在就再调用本方法获取一个,在就返回本
连接。
添加连接
触发机制:
1、 获取连接时,BasicResourcePool类prelimCheckoutResource方法调用。
调用过程:
1、 BasicResourcePool类prelimCheckoutResource方法当可用连接数为0时调用
recheckResizePool方法。
2、 _recheckResizePool方法判断需要扩容则调用expandPool方法
3、 expandPool方法使用线程池调用AcquireTask(实现Runnable接口)任务进行扩容。 4、 AcquireTask调用mgr.acquireResource方法获取连接,如果连接池里的连接未到最
大数量将获取的连接加入管理和未使用的list中,否则销毁连接。
关闭(回收)连接
触发机制:
应用程序调用连接的close方法。
调用过程:
1、 C3P0PooledConnectionPool类里的ConnectionEventListenerImpl监听器类的
connectionClosed方法被触发。
2、 判断同步还是异步(默认是同步)。异步就采用线程池来处理回收,同步就直接调用
BasicResourcePool类的checkinResource方法对连接进行回收,注意是回收不是关闭物
理连接。
死锁
C3p0很多操作都是多线程来处理的(如:添加连接,回收连接等),所以进行必要的死锁检测。
由ThreadPoolAsynchronousRunner类的子类DeadlockDetector来执行具体的操作。
DeadlockDetector类继承了TimerTask,由Timer来调度DeadlockDetecto运行。 DeadlockDetector类有2个属性:
LinkedListlast = null; LinkedListcurrent = null;
这2个list放的是待执行的任务,根据属性名就知道last是上次检测时待执行的任务,current是这次检测时要执行的任务,当pendingTasks(当前要执行的任务,克隆给current)不为空且current.equals( last )时认为死锁发生。
死锁发生后,当前任务交给ThreadPerTaskAsynchronousRunner类来处理,这个类会启用新的线程DispatchThread来处理当前的任务队列。
小结
c3p0是现在用的比较广泛的连接池之一,获取连接的效率有待提高,使用jdk1.6之前的可以考虑