c3p0获取连接Connection后的Close()---释疑
生活随笔
收集整理的这篇文章主要介绍了
c3p0获取连接Connection后的Close()---释疑
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
- 论题:
- java c3p0获取连接Connnection 之后, 调用 con.close( ) 是否真的关闭了物理连接 ?
- 简答:
- c3p0采用连接池, 目的就是提前预置一定数量的连接, 在使用时候重复利用这些连接, 所以, con.close() 之后, 物理连接当然是被放回了连接池, 而没有真正的关闭 .
- c3p0中的池连接(指:Connection) 是实现了PooledConnection接口的, PooledConnection为连接池管理提供钩子 (hook) 的对象, 它会在connnection被操作时接收到消息, 从而对该操作加以干涉,将Connection连接放回连接池.
- 疑问:
- 一些童鞋经过试验,发现如下问题,于是发出路上疑问, con.close()真的关闭了连接吗...
- 1 public class MyTest {
2 /**
3 * 开启了20个线程,返回的hashcode,如下:没有重复的
4 *1730967171 1122742512 156948859 1210106945 1217158489
5 *1868341939 1595154849 1873764403 1937202425 1629470861
6 */
7 public static void main(String[] args) {
8 for (int i = 0; i < 10; i++) {
9 new Thread(new Runnable() {
10 @Override
11 public void run() {
12
13 Connection con = JDBCUtil.getConnection();
14 System.out.println(con.hashCode());
15 // ....
16 con.close();
17 } catch (SQLException e) {
18 e.printStackTrace();
19 }
20 }
21 }).start();
22 }
23 }
24 }
25 public class JDBCUtil {
26 /**
27 * <!-- 最大空闲时间设置为0 , 即永不过期 -->
28 * <property name="maxIdleTime">0</property>
29 * <!-- 最多有多少个连接 -->
30 * <property name="maxPoolSize">5</property>
31 * <!-- 最少几个连接 -->
32 * <property name="minPoolSize">2</property>
33 */
34 private static Connection conn;
35 private static ComboPooledDataSource ds = new ComboPooledDataSource();
36
37 public static Connection getConnection() {
38 try {
39 conn = ds.getConnection();
40 } catch (SQLException e) {
41 e.printStackTrace();
42 }
43 return conn;
44 }
45 } View Code
-
c3p0源码跟踪 [ps : 水平有限,以下未解释java事件注册相关原理 ]
- 1 abstract class AbstractPoolBackedDataSource 2 extends PoolBackedDataSourceBase 3 implements PooledDataSource{ 4 //..... 5 6 // dataSource.getConnection()所调用的就是该方法 7 //implementation of javax.sql.DataSource 8 public Connection getConnection() throws SQLException{ 9 10 PooledConnection pc = 11 getPoolManager(). // 返回 C3P0PooledConnectionPoolManager 12 getPool(). // 返回 C3P0PooledConnectionPool 13 checkoutPooledConnection(); // 返回PooledConnection 14 return pc.getConnection(); 15 } 16 17 //..... 18 } 19 20 21 22 class C3P0PooledConnectionPool{ 23 // .... 24 public PooledConnection checkoutPooledConnection() throws SQLException{ 25 //System.err.println(this + " -- CHECKOUT"); 26 try 27 { 28 PooledConnection pc = (PooledConnection) this.checkoutAndMarkConnectionInUse(); 29 pc.addConnectionEventListener( cl ); 30 return pc; 31 } 32 catch (TimeoutException e) 33 { throw SqlUtils.toSQLException("An attempt by a client to checkout a Connection has timed out.", e); } 34 catch (CannotAcquireResourceException e) 35 { throw SqlUtils.toSQLException("Connections could not be acquired from the underlying database!", "08001", e); } 36 catch (Exception e) 37 { throw SqlUtils.toSQLException(e); } 38 } 39 40 private Object checkoutAndMarkConnectionInUse() throws TimeoutException, CannotAcquireResourceException, ResourcePoolException, InterruptedException 41 { 42 Object out = null; 43 boolean success = false; 44 while (! success) 45 { 46 try 47 { 48 out = rp.checkoutResource( checkoutTimeout ); 49 if (out instanceof AbstractC3P0PooledConnection) 50 { 51 // cast should succeed, because effectiveStatementCache implies c3p0 pooled Connections 52 AbstractC3P0PooledConnection acpc = (AbstractC3P0PooledConnection) out; 53 /* 54 *以下在获取物理连接的时候,PooledcConnection中注册的事件监听器会收到消息 55 *无论每次对connection的何种操作,PooledConnection都会收到来自驱动的消息, 56 *其中的钩子(hook)对象就会完成对Connection的回收 57 */ 58 Connection physicalConnection = acpc.getPhysicalConnection(); 59 success = tryMarkPhysicalConnectionInUse(physicalConnection); 60 } 61 else 62 success = true; //we don't pool statements from non-c3p0 PooledConnections 63 } 64 finally 65 { 66 try { if (!success && out != null) rp.checkinResource( out );} 67 catch (Exception e) { logger.log(MLevel.WARNING, "Failed to check in a Connection that was unusable due to pending Statement closes.", e); } 68 } 69 } 70 return out; 71 } 72 //.... 73 74 } View Code
- 综述:
- 当应用程序关闭连接时,它调用 Connection 方法 close。完成连接池时,连接池管理器将得到通知;因为它曾使用 ConnectionPool 方法 addConnectionEventListener 作为 ConnectionEventListener 对象注册它自身。连接池管理器释放到 PooledConnection 对象的句柄,并将 PooledConnection 对象返回到连接池,以便再次使用。因此,当应用程序关闭其连接时,基础物理连接会被回收而不是被关闭。
- 知识水平有限,难免错误,模糊, 请多批评指正,谢谢.
转载于:https://www.cnblogs.com/murthy/p/6495196.html
总结
以上是生活随笔为你收集整理的c3p0获取连接Connection后的Close()---释疑的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 【hdoj_2079】选课时间(母函数)
- 下一篇: APP统计