0

Java でマルチスレッドが必要なプログラムがあります。このMain関数は、MySQL DB に対してクエリを実行して値を選択し、一度に 1 つずつ各スレッドにname送信します。name

各スレッドは、 this に依存する操作を行いますnamerun関数はメソッドを呼び出します。たとえば、このmethod1メソッドClass1はいくつかの操作を実行し、table2 の DB に値をmethod2挿入します。また、table1 で操作と挿入を行う別のメソッドを呼び出します。

DB には table1 と table2 が 1 対多で含まれています。しかし、私はまだテーブルを接続していません。それらは今まで分離されています。table2ただし、特定のレコードが table1 のどのレコードにtable2属しているかを反映する列があります。table2 の DB は正しいが、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、DB にレコードを挿入する必要もありClass1ます。同期された inCalss2内にあるため、既に同期されているはずです。マルチスレッドを扱うのはまったく初めてです。ParenthesesClass1

コード構造のどこが間違っていますか? 私は周りMain.Stmt2.setStringMain.Stmt2.executeUpdate()一緒に正しいですsynchronizedか?? マルチスレッドを処理するときに DB の整合性を維持するにはどうすればよいですか?

4

1 に答える 1

0

トランザクションを使用して、データが両方のテーブルにあること、またはどちらにもないことを確認しましたか?
既存の 2 フェーズ コミット オプションが機能しない場合は、1 つのスレッドを使用して書き込みを行うか、独自の 2 フェーズ コミットを実装します。つまり、スレッド t3 は、スレッド t1 と t2 にコミットの準備ができている場合に通知します。スレッド t1 と t2 の両方が、yes または no で応答する必要があります。両方からの応答が「はい」の場合、スレッド t3 はスレッド t1 と t2 の両方にコミットを続行するように指示するか、コミットを続行しない/ロールバックを使用しないように指示できます。私はこれについてあまり考えていませんでした.3番目のスレッドの使用を避け、両方のスレッドがトランザクションをコミットする準備ができているかどうか、またはロールバックする必要があるかどうかを保存するために、両方のスレッドで共有されるデータ構造を使用することができます。

于 2012-07-06T21:46:48.333 に答える