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:
which is a sequential invocation of the
runQuerymethod on themyConnectionobject 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 itsrunmethod 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.