简体   繁体   English

Java JDBC查询在单独的线程锁父级中

[英]Java JDBC query in separate thread lock parent

I'm having some trouble understanding this. 我在理解这个问题上遇到了一些麻烦。 Here's what's happening. 这是正在发生的事情。 I'm spawning a new thread that holds a JDBC connection to a Oracle database. 我正在生成一个新的线程,它保存与Oracle数据库的JDBC连接。 When I ask it to connect to the database, the parent thread keeps running while the start() method is invoked but when I ask the child to execute a query (on a separate method), the parent thread gets stuck waiting for the child thread's method to finish doing its work. 当我要求它连接到数据库时,父线程在调用start()方法时继续运行但是当我要求子进行查询时(在单独的方法上),父线程被卡住等待子线程的完成工作的方法。 Any guess as how to fix this? 有什么猜测如何解决这个问题? Thanks in advance! 提前致谢!

public class Main extends Thread{

    public Main()
    {
    }

    public void myCounter() {
        int i = 0;
        DBConnection myConnection = null;
        for(;;)
        {
            i++;

            System.out.println("time: " + i);
            if( i  == 5)
            {
                myConnection = new DBConnection("localhost", 1521, "hr", "hr", "XE");
                myConnection.start();


            }
            if(i == 10)
                try {

                    myConnection.runQuery("Select * from hr.numbers order by dbms_random.value");
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void run()
    {
        myCounter();
    }

    public static void main(String[] args) {

        Main boot = new Main();
        boot.start();

    }

}

public class DBConnection extends Thread{

    Connection myConnection;
    int port;
    String user;
    String password;
    String serviceName;
    String host;


    public void run()
    {
        setUpConnection(host, port, user, password, serviceName);
    }
    /**
     * Sets up variables to create a connection to Oracle.
     *  
     * @param host      host
     * @param port      port
     * @param user      user
     * @param password  password
     */
    public DBConnection(String host, int port, String user, String password, String serviceName)
    {
        this.host = host;
        this.port = port;
        this.user = user;
        this.password = password;
        this.serviceName = serviceName;
    }


    private void setUpConnection(String host, int port, String user,
            String password, String dataBase) {
        System.out.println("-------- Oracle "
                + "JDBC Connection Testing ------------");

        try {

            Class.forName("oracle.jdbc.OracleDriver");

        } catch (ClassNotFoundException e) {

            System.out.println("Couldn't find Oracle JDBC Driver... :-(");
            e.printStackTrace();
            return;

        }

        System.out.println("Oracle JDBC Driver Registered!");
        myConnection = null;
        try {
            myConnection = DriverManager.getConnection(
                    "jdbc:oracle:thin:@//" 
                            + host 
                            + ":" 
                            + port 
                            + "/" 
                            + dataBase,
                            user, password
                    );

        } catch (SQLException e) {

            System.out.println("Connection Failed!");
            e.printStackTrace();
            return;

        }

        if (myConnection != null) {
            System.out.println("Connected to Oracle! :-)");
        } else {
            System.out.println("Failed to make connection!");
        }
    }


    /**
     * Queries the database and returns a ResultSet
     * @param  query            SQL
     * @throws SQLException 
     */
    public  ResultSet runQuery(String query) throws SQLException 
    {
        System.out.println("                                                    [DBConnection] Started Running @ " + (new SimpleDateFormat("HH:mm:ss:S")).format(new Date()));
        ResultSet rs = null;

        Statement stt = myConnection.createStatement();
        rs = stt.executeQuery(query);
        System.out.println("                                                    [DBConnection] Finished Running @: " + (new SimpleDateFormat("HH:mm:ss:S")).format(new Date()));
        return  rs;

    }

Here's the output I get: 这是我得到的输出:

time: 1
time: 2
time: 3
time: 4
time: 5
-------- Oracle JDBC Connection Testing ------------
Oracle JDBC Driver Registered!
time: 6
Connected to Oracle! :-)
time: 7
time: 8
time: 9
time: 10
                                                    [DBConnection] Started Running @ 14:46:00:660
                                                    [DBConnection] Finished Running @: 14:46:12:750
time: 11
time: 12
time: 13
time: 14

... ... .. . .......

I think you have misunderstood a bit how threads work. 我认为你误解了线程的工作原理。 The problem is that you are calling this on the parent thread: 问题是你在父线程上调用它:

myConnection.runQuery("Select * from hr.numbers order by dbms_random.value");

which is a sequential invocation of the runQuery method on the myConnection object that happens to be a thread . 这是对myConnection对象上的runQuery方法的顺序调用,恰好是一个线程 This does not mean that it will instruct the child to execute the method. 这并不意味着它会指示孩子执行该方法。 Instead the parent will execute it itself and the child thread finishes as soon as its run method has returned. 相反,父级将自己执行它,并且子线程在其run方法返回后立即完成。

If you want to have a separate thread that keeps receiving commands to execute queries you will have to implement a producer-consumer pattern, where the parent keeps queuing commands for the child to execute. 如果您希望有一个单独的线程继续接收执行查询的命令,则必须实现生产者 - 消费者模式,其中父级保持排队命令以便子进程执行。 To this end I recommend you look at ExecutorService . 为此,我建议您查看ExecutorService

When you call myConnection.runQuery() , you are inside the run() method of the parent thread, so you are not in the connection thread even if you call one of its methods. 当您调用myConnection.runQuery() ,您位于父线程的run()方法内,因此即使您调用其中一个方法,也不在connection线程中。

You should call runQuery inside the run() method of myConnection to achieve what you want. 你应该在myConnectionrun()方法中调用runQuery来实现你想要的。

Your runQuery method is blocking since you call it on the main thread (So it will wait until the query is finished). 你的runQuery方法是阻塞的,因为你在主线程上调用它(所以它会等到查询完成)。 If you want it to be called on another thread call it on the other's thread run method (just start the other thread where you would originally called for the query method) 如果你想在另一个线程上调用它,可以在另一个线程的run方法上调用它(只需启动你最初调用查询方法的另一个线程)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM