c3p0获取连接Connection后的Close()---释疑
- 论题:
- java c3p0获取连接Connnection 之后, 调用 con.close( ) 是否真的关闭了物理连接 ?
- 简答:
- c3p0采用连接池, 目的就是提前预置一定数量的连接, 在使用时候重复利用这些连接, 所以, con.close() 之后, 物理连接当然是被放回了连接池, 而没有真正的关闭 .
- c3p0中的池连接(指:Connection) 是实现了PooledConnection接口的, PooledConnection为连接池管理提供钩子 (hook) 的对象, 它会在connnection被操作时接收到消息, 从而对该操作加以干涉,将Connection连接放回连接池.
- 疑问:
- 一些童鞋经过试验,发现如下问题,于是发出路上疑问, con.close()真的关闭了连接吗...
public class MyTest {
/**
* 开启了20个线程,返回的hashcode,如下:没有重复的
*1730967171 1122742512 156948859 1210106945 1217158489
*1868341939 1595154849 1873764403 1937202425 1629470861
*/
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() { Connection con = JDBCUtil.getConnection();
System.out.println(con.hashCode());
// ....
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}).start();
}
}
}
public class JDBCUtil {
/**
* <!-- 最大空闲时间设置为0 , 即永不过期 -->
* <property name="maxIdleTime">0</property>
* <!-- 最多有多少个连接 -->
* <property name="maxPoolSize">5</property>
* <!-- 最少几个连接 -->
* <property name="minPoolSize">2</property>
*/
private static Connection conn;
private static ComboPooledDataSource ds = new ComboPooledDataSource(); public static Connection getConnection() {
try {
conn = ds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
}c3p0源码跟踪 [ps : 水平有限,以下未解释java事件注册相关原理 ]
abstract class AbstractPoolBackedDataSource
extends PoolBackedDataSourceBase
implements PooledDataSource{
//..... // dataSource.getConnection()所调用的就是该方法
//implementation of javax.sql.DataSource
public Connection getConnection() throws SQLException{ PooledConnection pc =
getPoolManager(). // 返回 C3P0PooledConnectionPoolManager
getPool(). // 返回 C3P0PooledConnectionPool
checkoutPooledConnection(); // 返回PooledConnection
return pc.getConnection();
} //.....
} class C3P0PooledConnectionPool{
// ....
public PooledConnection checkoutPooledConnection() throws SQLException{
//System.err.println(this + " -- CHECKOUT");
try
{
PooledConnection pc = (PooledConnection) this.checkoutAndMarkConnectionInUse();
pc.addConnectionEventListener( cl );
return pc;
}
catch (TimeoutException e)
{ throw SqlUtils.toSQLException("An attempt by a client to checkout a Connection has timed out.", e); }
catch (CannotAcquireResourceException e)
{ throw SqlUtils.toSQLException("Connections could not be acquired from the underlying database!", "08001", e); }
catch (Exception e)
{ throw SqlUtils.toSQLException(e); }
} private Object checkoutAndMarkConnectionInUse() throws TimeoutException, CannotAcquireResourceException, ResourcePoolException, InterruptedException
{
Object out = null;
boolean success = false;
while (! success)
{
try
{
out = rp.checkoutResource( checkoutTimeout );
if (out instanceof AbstractC3P0PooledConnection)
{
// cast should succeed, because effectiveStatementCache implies c3p0 pooled Connections
AbstractC3P0PooledConnection acpc = (AbstractC3P0PooledConnection) out;
/*
*以下在获取物理连接的时候,PooledcConnection中注册的事件监听器会收到消息
*无论每次对connection的何种操作,PooledConnection都会收到来自驱动的消息,
*其中的钩子(hook)对象就会完成对Connection的回收
*/
Connection physicalConnection = acpc.getPhysicalConnection();
success = tryMarkPhysicalConnectionInUse(physicalConnection);
}
else
success = true; //we don't pool statements from non-c3p0 PooledConnections
}
finally
{
try { if (!success && out != null) rp.checkinResource( out );}
catch (Exception e) { logger.log(MLevel.WARNING, "Failed to check in a Connection that was unusable due to pending Statement closes.", e); }
}
}
return out;
}
//.... }
- 综述:
- 当应用程序关闭连接时,它调用
Connection方法close。完成连接池时,连接池管理器将得到通知;因为它曾使用ConnectionPool方法addConnectionEventListener作为ConnectionEventListener对象注册它自身。连接池管理器释放到PooledConnection对象的句柄,并将PooledConnection对象返回到连接池,以便再次使用。因此,当应用程序关闭其连接时,基础物理连接会被回收而不是被关闭。 - 知识水平有限,难免错误,模糊, 请多批评指正,谢谢.
- 当应用程序关闭连接时,它调用
c3p0获取连接Connection后的Close()---释疑的更多相关文章
- mysql获取连接connection失败
好久不写jdbc了,今天写了个小东西,数据库连接失败,错误信息如下: java.sql.SQLException: The server time zone value '???ú±ê×??±??' ...
- 选择c3p0作为连接池
<hibernate-configuration> <session-factory> <property name="dialect& ...
- Hibernate整合C3P0实现连接池
Hibernate整合C3P0实现连接池 hibernate中可以使用默认的连接池,无论功能与性能都不如C3PO(网友反映,我没有测试过),C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI ...
- JDBC获取数据库Connection的工具抽取
使用JDBC获取数据库的连接,大字分为三个步骤 1.获取驱动包名,定义URL,database_username,database_password 2.获取Connection对象 3.利用Conn ...
- 事务处理中如何获取同一个connection 对象
运用线程内部的map属性,将对象绑定到ThreadLocal中: 具体实现: 1.新建一个绑定Connection对象的单例类 public class ConnectionBind { privat ...
- JDBC(二)—— 获取连接池方式
## 获取数据库连接的方式 ### 方式一 ```javaDriver driver = new com.mysql.cj.jdbc.Driver(); String url = "jdbc ...
- WzwJDBC 自定义工具类(获取连接,释放资源)
package wzwUtil;import java.io.IOException;import java.io.InputStream;import java.sql.*;import java. ...
- idea启动服务连接mysql后 Navicat连接mysql就报错2013-Lost connection toMySQL server at
我是使用navicat的windows端 连接centos下mysql服务器 第一次常规连接mysql正常,idea启动服务连接mysql后 Navicat连接mysql就报错2013-Lost co ...
- Java Web(十) JDBC的增删改查,C3P0等连接池,dbutils框架的使用
前面做了一个非常垃圾的小demo,真的无法直面它,菜的抠脚啊,真的菜,好好努力把.菜鸡. --WH 一.JDBC是什么? Java Data Base Connectivity,java数据库连接,在 ...
随机推荐
- 微软2017MVP大礼包拆箱攻略
容我本周偷个懒,晒个大礼包就糊弄过去了.13号晚上拿到的大礼包,激动的没敢拆,一直等到娃睡着了,才偷偷打开了快递,忍了两天没忍住,上来晒图得瑟一下,请各位轻拍,谢谢! 1.大礼包的盒子(联邦快递的盒子 ...
- iOS 解决一个复杂bug 之 计分卡
由于该模块界面和业务逻辑都很复杂,并且整个界面设计和业务逻辑都在ViewController(下面简称为VC)里面完成.该VC共有3000多行,一个函数几百张的也有.所以,解决起来真是头疼. 1. 问 ...
- php短数组写法
在php 5.4+的版本中,可以使用 [] 来表示 array() 例子: // On PHP 5.1 $data = array("foo", "bar" ...
- Angular - - angular.forEach、angular.extend
angular.forEach 调用迭代器函数取每一项目标的集合,它可以是一个对象或数组.迭代器函数与迭代器(value.key)一起调用,其中值是一个对象属性或数组元素的值,而数组元素是对象属性的关 ...
- iOS 之 const
const int a与 int const a一样. const int *a ;//指针可以修改,指向常整形的指针 int* const a;// 常指针, int* 作为一个整体被限制, 所以指 ...
- SQL server存储过程:数据的插入和更新
存储过程的功能非常强大,在某种程度上甚至可以替代业务逻辑层, 接下来就一个小例子来说明,用存储过程插入或更新语句. 1.数据库表结构 所用数据库为Sql Server2008. 2.创建存储过程 (1 ...
- 固定表头带滚动条的HTML表格
http://blog.csdn.net/daryl715/article/details/1883677 <html> <head> </head> <BO ...
- 有效的GOCsharpHelper1.0(源代码开放)
csharp编写界面,调用基于opencv的图像处理类库,是解决一类问题的优良方法.经过不懈研究,有最新进展: 一.目前情况和优点 位置在11.通过clr 架在c ...
- 如何在项目中引入MetaQ消息收发机制
当需要异步发送和接收大量消息时,需要在Crystal项目中引入MetaQ消息收发机制. 关于MetaQ使用的官方例子可参考:https://github.com/killme2008/Metamorp ...
- Redis 介绍与安装
Redis 是Key-Value 类型的内存数据库,支持多数据结构,性能非常出色,每秒处理十万次读写操作. 整个大致的过程是: 整个数据库加载到内存中,操作之,通过异步定期处理数据库数据的刷新到硬盘 ...