java - Jdbc DataSource多线程不释放连接

标签 java multithreading jdbc

我已经为此花费了很多时间,但没有成功。我正在多线程应用程序中实例化数据源。所有线程都从数据源获取连接并在finally block 中关闭它们(我逐行检查以确保连接已释放)。我遇到的问题是,即使在每个连接上调用 close 方法,它们也不会被数据源释放。我知道这一点是因为我有一个不同的线程从 DBCP 数据源打印 source.getNumActive()

这是基本设置。

public class DataSourceHolder {
  private static DataSource source;
  static {
    get the data source either from jndi or created from scratch
  }
  public DataSource getDataSource() { return source; }
}

我有一个简单的 JdbcPattern (类似于 springs JdbcTemplate 但非常简单)来封装所有样板代码。其定义如下:

public class JdbcPattern {
  private DataSource source;
  public JdbcPattern(DataSource source) {
    this.source = source;
  }
  public int executeMethods(....) {
    Connection c = source.getConnection();
    try {
      .. do the statements
    } finally {
      try { c.close(); } catch (SQLException ignore) { }
    }
  }
  public List<?> queryMethods(....) {
  }
}  

最后,我有四个线程在程序开始时启动。该线程会 hibernate 一段时间,并在唤醒时使用 DataSourceHolder 提供程序 DataSource 实例化 JdbcPattern 并开始执行操作。事情完成后,当连接关闭时,数据源并没有真正释放它。在数据源最大连接数之后,程序由于无法实例化更多连接而卡住。

您将如何诊断这个问题?

编辑。这是在tomcat上运行的。所有常用方法均由 Catalina 通用加载器加载,线程在 Web 应用程序之一内运行。我一直在想这可能是一个类加载器问题。

最佳答案

您不应该忽略关闭失败。将其包装在未经检查的异常中或将其记录下来,但不要忽略。如果尝试释放与池的连接时出现一些奇怪的错误,您将不会知道。

我建议您为池数据源创建自己的包装器。您可以记录对 getConnection 的调用以及堆栈跟踪和连接的唯一标识符。当 JdbcPattern 调用 close 时,也以相同的方式记录它。找到未关闭的连接的标识符,注意它们是从 getConnection 堆栈跟踪中从池中取出的位置。您还可以让 DataSource 包装器在服务器内执行此分析,但这样会需要更多代码,并且出错的可能性也更大。我会先尝试简单的日志记录。考虑将此日志记录保留在产品中,但低于正常的日志记录阈值。您将再次需要它。

关于java - Jdbc DataSource多线程不释放连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10964842/

相关文章:

java - 我是否有重新排序问题,是否由于引用转义?

java.lang.UnsatisfiedLinkError : no mkl_rt in java. 库.path

java - 向 RecyclerView 项目添加涟漪效果时“可能过度绘制”

java - 让java插件使用浏览器证书

使用用户输入控制 POSIX 线程

java - 如何使用 jOOQ 获取事务内部的底层连接?

java - 为什么在方法重载中加宽比 Boxing 和 var-args 都好?

iphone - iOS 应用未能及时启动 0x000000008badf00d - applicationDidBecomeActive 延迟

java - 随着时间的推移,SQLite 插入缓慢到爬行

mysql - 匹配 MySQL 列中的空字符串,而不是空值