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. 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. 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. 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.
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.
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.
You should call runQuery
inside the run()
method of myConnection
to achieve what you want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With