【问题标题】:Thread deadlock relevant to methods GetConnection() from DriverManager and next() from Scanner, System.in与 DriverManager 中的 GetConnection() 方法和 Scanner、System.in 中的 next() 方法相关的线程死锁
【发布时间】:2014-06-16 08:12:52
【问题描述】:

关于以下问题,我需要您的帮助: 我有两个线程

第一个线程:应该使用 Scanner 类从标准输入读取用户输入

扫描仪扫描仪=新的扫描仪(System.in);

并且正在等待整个字符串。该线程首先获得到方法 next()。

第二个线程在之后到达并尝试使用 jdbc - odbc 打开连接。

connection = DriverManager.getConnection("jdbc:odbc:baza");

发生的是方法 getConnection() 和第二个线程被第一个阻塞。我的问题是为什么会这样?我怎样才能防止这种情况?

我已经从我的项目中创建了小代码,所以它更容易阅读..

我感兴趣的另一件事是为什么

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

是可选的。我的程序有无它都可以工作吗? java默认加载驱动吗?

代码:

public class StartingHere implements Runnable {
    public static void main(String[] args) {
        //SECOND THREAD
        try {
            StartingHere sh =  new StartingHere();
            Thread thread = new Thread(sh);
            thread.start();
            //DELAYING SECOND THREAD. 
            Thread.currentThread().sleep(1000);
            DBConnection dbConnection = new DBConnection();
        } catch (Exception ex) {
            System.out.println("Check db url for in DBConnection");
            ex.printStackTrace();
        }
    }

    @Override
    public void run() {
        //FIRST THREAD - Waiting for user to input String
        String userInput = null;
        Scanner scanner = new Scanner(System.in);
        while(!"end".equals(userInput)) {
            //Waiting for whole string
            userInput = scanner.next();
        }
    }
}

public class DBConnection {
    Connection connection;

    public DBConnection() throws SQLException, ClassNotFoundException {
        Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
        // SECOND THREAD- Problem! Here program hangs until FIRST THREAD got some input.. why?
        connection = DriverManager.getConnection("jdbc:odbc:baza");
        System.out.println("DBConnection: 'Connected'");
    }
}

【问题讨论】:

  • S̶e̶e̶ ̶h̶t̶t̶p̶:̶/̶/̶s̶t̶a̶c̶k̶o̶v̶e̶r̶f̶l̶o̶w̶.̶c̶o̶m̶/̶q̶u̶e̶s̶t̶i̶o̶n̶s̶/̶1̶8̶2̶8̶8̶0̶5̶8̶/̶h̶o̶w̶-̶i̶s̶-̶d̶r̶i̶v̶e̶r̶-̶c̶l̶a̶s̶s̶-̶l̶o̶c̶a̶t̶e̶d̶-̶i̶n̶-̶j̶d̶b̶c̶4̶ ̶f̶o̶r̶ ̶w̶h̶y̶ ̶t̶h̶e̶ ̶d̶r̶i̶v̶e̶r̶ ̶i̶s̶ ̶l̶o̶a̶d̶e̶d̶ ̶a̶u̶t̶o̶m̶a̶t̶i̶c̶a̶l̶l̶y̶.̶ The JDBC-ODBC driver是 JRE 的一部分,因此会自动加载。
  • 我用你的例子来调用 getConnection()。
  • 这很奇怪。我复制了所有代码,但它不起作用。我没有写;我认为这无关紧要,但我们开始吧:它是由 WindowsXP 上的 NetBeans 8.0 Platform JDK 1.7 构建的。一旦我在其他机器上尝试(今天不能这样做),我会在这里发布。但这将是最好的解决方案,因为我看不到连接为什么会出现死锁。谢谢你的回复!
  • 我没有连接,因为我没有访问数据库的权限,但是我得到了一个异常,如果我删除了调用,DBConnection: 'Connected' 会被打印出来。也许您与数据库的连接有问题。尝试删除调用,看看是否打印了字符串。
  • 不要评论/删除 DriverManager.getConnection("jdbc:odbc:baza");。因为这种方法是一种制造锁的方法。如果您可以制作虚拟 MSAcess 数据库并将其注册到 Windows ODBC 中,并为其赋予符号名称“baza”。这样 url (getConnection("jdbc:odbc:baza");) 就可以找到它。

标签: java multithreading deadlock stdin


【解决方案1】:

我的程序有无它都可以工作吗? java默认加载驱动吗?

来自使用JDBC 4Java 7,这是可选的。它将自动在类路径中找到正确的驱动程序类并加载它。无需使用Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); 加载它。但对于早期版本,您必须这样做。

关于你的死锁问题,如果你所说的真正原因是那么你可以在启动线程后调用join()

thread.start();
thread.join();

如果你说你的代码正在等待

connection = DriverManager.getConnection("jdbc:odbc:baza");

这似乎是一个死锁情况,因为即使扫描仪也在等待用户输入,那么我认为您的连接需要很长时间才能连接。您可以通过为此指定超时来尝试。你可以这样做

DriverManger.setLoginTimeout(10);

【讨论】:

  • 这回答了我问题的后半部分!至于第一部分,我想了解为什么会发生死锁。我知道你总是可以解决问题 :-) 非常感谢 Aniket! :-D
  • 请查看编辑后的答案,看看是否有帮助。
  • GetConnection() 工作正常,如果到达“FIRST”线程之前立即连接。如果它没有首先到达,它会挂起,直到扫描仪解除阻塞“第二个”线程。超时我只会取消建立连接,所以它不是一个选项:-(
  • 哦.. 在这种情况下,上下文切换不会发生,并且在支持多编程的系统中不应该发生这种情况。如果您使用的是 IDE,则可以调试代码。同样在调试点属性之前将调试方法设置为线程级别。
  • 我会试试的。感谢 Aniket 回复
猜你喜欢
  • 2021-07-11
  • 1970-01-01
  • 1970-01-01
  • 2016-08-30
  • 2014-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多