• 论题:

    • 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()---释疑的更多相关文章

  1. mysql获取连接connection失败

    好久不写jdbc了,今天写了个小东西,数据库连接失败,错误信息如下: java.sql.SQLException: The server time zone value '???ú±ê×??±??' ...

  2. 选择c3p0作为连接池

    <hibernate-configuration>     <session-factory>         <property name="dialect& ...

  3. Hibernate整合C3P0实现连接池

    Hibernate整合C3P0实现连接池 hibernate中可以使用默认的连接池,无论功能与性能都不如C3PO(网友反映,我没有测试过),C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI ...

  4. JDBC获取数据库Connection的工具抽取

    使用JDBC获取数据库的连接,大字分为三个步骤 1.获取驱动包名,定义URL,database_username,database_password 2.获取Connection对象 3.利用Conn ...

  5. 事务处理中如何获取同一个connection 对象

    运用线程内部的map属性,将对象绑定到ThreadLocal中: 具体实现: 1.新建一个绑定Connection对象的单例类 public class ConnectionBind { privat ...

  6. JDBC(二)—— 获取连接池方式

    ## 获取数据库连接的方式 ### 方式一 ```javaDriver driver = new com.mysql.cj.jdbc.Driver(); String url = "jdbc ...

  7. WzwJDBC 自定义工具类(获取连接,释放资源)

    package wzwUtil;import java.io.IOException;import java.io.InputStream;import java.sql.*;import java. ...

  8. idea启动服务连接mysql后 Navicat连接mysql就报错2013-Lost connection toMySQL server at

    我是使用navicat的windows端 连接centos下mysql服务器 第一次常规连接mysql正常,idea启动服务连接mysql后 Navicat连接mysql就报错2013-Lost co ...

  9. Java Web(十) JDBC的增删改查,C3P0等连接池,dbutils框架的使用

    前面做了一个非常垃圾的小demo,真的无法直面它,菜的抠脚啊,真的菜,好好努力把.菜鸡. --WH 一.JDBC是什么? Java Data Base Connectivity,java数据库连接,在 ...

随机推荐

  1. js原生设计模式——4安全的工厂方法模式之Factory方法模式

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  2. qlv格式转换成MP4格式

    腾讯视频下载:1.先下载腾讯的客户端--->播放视频在客户端 2.播放视频一段后停止 3.点击腾讯客户端的右上角的设置 4.复制缓存地址(注意:在此之前需要设置"显示隐藏的文件夹&qu ...

  3. Intent的属性及Intent-filter配置——指定Action、Category调用系统Activity

    Intent代表了启动某个程序组件的“意图”,实际上Intent对象不仅可以启动本应用内程序组件,也可启动Android系统的其他应用的程序组件,包括系统自带的程序组件——只要权限允许. 实际上And ...

  4. Windows Server 2008 R2防火墙入站规则

    一般服务器的端口都设置了外网无法访问,iis中创建的网站外网也是访问不了的,需要创建指定端口的入站规则后方可访问. 方法/步骤     服务器管理器-->配置-->高级安全windows防 ...

  5. NOIP 提高组必会!(转)

    1.排序算法(快排.选择.冒泡.堆排序.二叉排序树.桶排序)2.DFS/BFS 也就是搜索算法,剪枝务必要学! 学宽搜的时候学一下哈希表!3.树 ①遍历 ②二叉树 ③二叉排序树(查找.生成.删除) ④ ...

  6. 如何在windows xp下实现声音内录

    问题描述: 用屏幕录制软件录制一个视频,能够成功录制视频,但无法录制视频里面的声音. 问题原因: 因为现在的多数声卡,均无法直接通过声卡自身的功能实现内录和立体声混音. 这是由于声卡芯片厂商迫于RIA ...

  7. MalformedObjectNameException: Invalid character '' in value part of property

    http://blog.csdn.net/getdate/article/details/6729706 ojdbc6.jar的问题: 最近在项目中用spring配置oracle数据库连接池, 启动的 ...

  8. 【开发必备】今天我们来谈谈Android NDK动态链接库(so文件)的一些见解

    一.写在前面 直到现在,基本我写的每一个项目都会用到NDK动态链接库的知识,可见这个也的确十分常用.那么,今天,咱们就来谈谈它. 二.什么是ABI和so 1.发展 早起的Android系统几乎只支持A ...

  9. CodeForces758D

    D. Ability To Convert time limit per test:1 second memory limit per test:256 megabytes input:standar ...

  10. Spring之循环依赖

    转:http://my.oschina.net/tryUcatchUfinallyU/blog/287936 概述 如何检测循环依赖 循环依赖如何解决 Spring如何解决循环依赖 主要的几个缓存 主 ...