0

我在这里有一个基本问题 - 我正在使用一个名为XpressMP.

我编写了一个多线程程序来将大量记录插入数据库。在连接数据库时,我注意到一件最重要的事情:

在我的程序中,如果我使用类似下面的东西 -

class Task implements Runnable {

   private Connection dbConnection = null;
   private PreparedStatement preparedStatement = null;

   //other stuff

 @Override
  public void run() {

   try {

      dbConnection = getDBConnection();

   } finally {
        if (preparedStatement != null) {
            try {
                preparedStatement.close();
                preparedStatement = null;
            } catch (SQLException e) {
            }
        }
        if (dbConnection != null) {
            try {
                dbConnection.close();
                dbConnection = null;
            } catch (SQLException e) {
            }
        }
    }
  }
}

它工作正常,我正在关闭最后一个块中的每个连接。而且我可以在数据库中插入更多行。

但是,一旦我开始有意地(我不应该这样做)使用多个线程的静态连接-

class Task implements Runnable {

   private static Connection dbConnection = null;
   private static PreparedStatement preparedStatement = null;

   //other stuff

 @Override
  public void run() {

  try {

    dbConnection = getDBConnection();

   } finally {
        if (preparedStatement != null) {
            try {
                preparedStatement.close();
                preparedStatement = null;
            } catch (SQLException e) {

            }
        }
        if (dbConnection != null) {
            try {
                dbConnection.close();
                dbConnection = null;
            } catch (SQLException e) {
            }
        }
    }
  }
}

整个数据库挂起。在重新启动数据库之前,我无法使用该数据库。所以这意味着我的 JDBC 驱动程序存在一些问题。我已经将这个问题告诉了 DBA,他们正在与拥有该数据库的人交谈。

但我的问题是它为什么会挂起。是什么原因?

4

2 回答 2

1

您在各个线程之间共享一个对象引用变量...有时,创建一个连接对象,然后在它关闭(并将其引用设置为空)之前,另一个线程启动,创建另一个对象并且从不关闭旧对象。因此,该连接仍然存在,并且在某个时间点,将打开太多连接,并且您的 DBMS 可能会崩溃,并出现诸如“连接过多”之类的错误。问题不在于您的驱动器,而在于您的代码。请注意,某些线程也可能关闭由另一个线程创建的连接!

我认为您没有看到正在抛出的异常,因为您没有 a catchin you outer try。当您尝试创建连接时将抛出异常。尝试在那里放置一个 catch 以显示堆栈跟踪。如果您的数据库检测到此问题,它将起作用(它可能会起作用)。

于 2013-02-08T03:17:48.220 回答
1

JDBC 不是线程安全的,因此您不应并行使用来自多个线程的一个 Connection 对象,无论它是否存储在静态字段中。一旦你这样做了,一个线程可能会在另一个线程的查询中间发送它的查询,所以数据库将收到完整的垃圾,如果数据库不是坚如磐石,这些垃圾可能会破坏数据库。

于 2013-02-08T04:42:43.077 回答