c3p0源码分析

数据源 
入口类: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之前的可以考虑

你可能感兴趣的:(数据库)