Reputation: 20082
I have a program that needs multi-threading in Java. The Main
function make a query to MySQL DB to select a value name
and send one name
at a time to each thread.
Each thread will make operations that rely on this name
. The run
function calls a method say, method1
in Class1
, this method perform some operations & insert values in the DB in table2, also, it calls another method, method2
that does operations and insertions in table1.
The DB contains table1 & table2, one-to-many. But I have not connected the tables yet, they are separated till now. But there is a column in table2
that reflects to which record in table1 a certain record in table2
belongs. My DB in table2 are correct, but in table1 are wrong (ex: the first 3 records are not inserted, while I found the related records to them in table2 are inserted, or some times wrong values for another record inserted in else record, etc).
I assigned the name
value in the thread constructor. This concerned part in the Main
class looks like:
PreparedStatement Stmt1=null; //for the first table
PreparedStatement Stmt2=null; //for the second table
private static Statement statement = null;
private static ResultSet resultSet = null;
String name=null;
String query1=null, query2=null;
try {
DBConnection.ConnectDB(); //connect to database
query1 = " insert into schema1.table1 values
(default,?,?)";
query2 = " insert into sechema1.table2 values (default,?,?)";
Stmt1 = DBConnection.con.prepareStatement(query1);
Stmt2 = DBConnection.con.prepareStatement(query1);
statement = DBConnection.con.createStatement();
resultSet = statement.executeQuery("select name from schema1.table1");
ExecutorService threadExecutor = Executors.newFixedThreadPool(10 );
while(resultSet.next())
{
myname=resultSet.getString("Column1");
MyRunnable task1 = new MyRunnable( myname);
threadExecutor.execute( task1 );
nameCounter++;
}
threadExecutor.shutdown();
// Wait until all threads are finish
while (! threadExecutor.isTerminated()) { }
System.out.println("Finished all threads");
DBConnection.con.close();
}// end try
catch (Exception e) {
e.printStackTrace();
}
The MyRunnable class is as following:
public class MyRunnable implements Runnable{
private String threadName=null;
private int threadCounter; //to count how many names we have selected
MyRunnable2 (String name)
{
synchronized (this){ //I used synchronized as I want to avoid two threads
//taking the same value.
this.threadHostName=name;
this.threadCounter=Main.nameCounter; } //end synchronize
}
public void run()
{
// Here I make a call for the Class1 method1 that I want the thread to perform
} //end run()
} //end class MyRunnable
public void Class1 {
public void method1(String name)
{
//some calculations
//I used synchronized to make the DB records correctly inserted
synchronized(this) { //
for (int i = 0; i < Value.length; i++)
{
//here I need to insert values in table 2
try {
synchronized(this){
Main.Stmt2.setString (1, string1);
Main.Stmt2.setString (2, string2);
Main.Stmt2.executeUpdate();
}
catch (Exception e)
{
System.out.println("DB_Error:_"+ e.toString());
}
} //end for
// Here I made a call for method2 in Class2
} //end synchronized
} //end method1
} //end class1
In Class2
, I also need to insert records to the DB, I did the same way in Class1
. Calss2
already supposed to be synchronized as it is inside the synchronized Parentheses
in Class1
. I am completely new to deal with multi-threading.
What is wrong in my code structure ? Am I correct in surrounding Main.Stmt2.setString
and Main.Stmt2.executeUpdate()
with synchronized
?? How can I maintain DB integrity when dealing with multi-threadings?
Upvotes: 0
Views: 494
Reputation: 20232
Have you tried using transactions to ensure that data is in both tables or in neither?
If any existing two phase commit options do not work, either use one thread to do the writes or implement your own two phase commit i.e. thread t3 signals threads t1 and t2 if they are ready to commit. Both threads t1 and t2 must reply with a yes or no response. If the response is yes from both, thread t3 can tell both threads t1 and t2 to proceed with the commit or else tell them not to proceed with the commits/use rollbacks. I have not given this too much thought - one could probably avoid using a third thread and use a data structure shared by both threads to store whether both threads are ready to commit or should rollback the transactions.
Upvotes: 0