Jdbc DataSource多线程不重新连接

时间:2012-06-09 21:51:07

标签: java multithreading jdbc

我已经花了好几个小时没有成功。我在多线程应用程序中实例化一个DataSource。所有线程都从DataSource获取连接并在finally块中关闭它们(我已逐行删除以确保释放连接)。我遇到的问题是,即使在每个连接上调用close方法,它们都不会被DataSource释放。我知道这是因为我有一个不同的线程从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(比如spring 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(....) {
  }
}  

最后,我有四个线程在程序开始时开始。这个线程会休眠一段时间,并在唤醒时使用DataSourceHolder提供程序DataSource实例化一个JdbcPattern并开始执行操作。这些东西完成了,当连接关闭时,DataSource并没有真正释放它。在DataSource最大连接之后,程序冻结,因为不能再实例化连接。

你会如何诊断?

EDIT。这是在tomcat上运行的。所有常用方法都由catalina公共加载器加载,并且线程在其中一个Web应用程序中运行。我一直在想它可能是一个类加载器问题。

1 个答案:

答案 0 :(得分:2)

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

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