0

我有一个需要 Java 多线程的程序。该Main函数对 MySQL DB 进行查询以选择一个值name并一次将一个值发送name到每个线程。

每个线程都会进行依赖于此的操作name。该run函数调用一个方法,例如,method1Class1方法执行一些操作并在 table2 中的 DB 中插入值,此外,它还调用另一个方法,method2该方法在 table1 中执行操作和插入。

数据库包含表 1 和表 2,一对多。但是我还没有连接表,它们直到现在都是分开的。但是其中有一列table2反映了table1中的某个记录table2属于哪个记录。我在 table2 中的数据库是正确的,但在 table1 中是错误的(例如:前 3 条记录没有插入,而我发现在 table2 中插入了与它们相关的记录,或者有时在 else 记录中插入的另一条记录的值错误等)。

我在线程构造函数中分配了name值。课堂上的这个相关部分Main如下所示:

      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();
            }

MyRunnable 类如下:

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

Class2中,我还需要向数据库中插入记录,我在Class1. Calss2已经应该是同步的,因为它在同步Parentheses的 in 中Class1。我对处理多线程完全陌生。

我的代码结构有什么问题?我在周围Main.Stmt2.setStringMain.Stmt2.executeUpdate()周围是否正确synchronized?处理多线程时如何保持数据库完整性?

4

1 回答 1

0

您是否尝试过使用事务来确保数据在两个表中或都不在两个表中?
如果任何现有的两阶段提交选项不起作用,要么使用一个线程进行写入,要么实现您自己的两阶段提交,即线程 t3 向线程 t1 和 t2 发出信号,如果它们准备好提交。线程 t1 和 t2 都必须回复是或否。如果两者的响应都是肯定的,线程 t3 可以告诉线程 t1 和 t2 继续提交,或者告诉他们不要继续提交/使用回滚。我没有考虑太多 - 可能会避免使用第三个线程并使用两个线程共享的数据结构来存储两个线程是否准备好提交或应该回滚事务。

于 2012-07-06T21:46:48.333 回答