2016-05-31 6 views
2

私は結果セットをマルチスレッドしようとしています。多くのスレッドのうちの1つにnext()を呼び出すと、必ず他のすべてのスレッドがロックアウトされていることを確認したい。多くのスレッドがnext()メソッドを同時に呼び出すと、行がスキップされるため、これは重要です。ここに私は何をしたのですか結果セットオブジェクトを同期ロックしますか?

public class MainClass { 
    private static ResultSet rs; 

    public static void main (String [] args) { 

     Thread thread1 = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       runWhile(); 
      }}); 
     Thread thread2 = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       runWhile(); 
      }}); 

     thread1.start(); 
     thread2.start(); 
     thread1.join(); 
     thread2.join(); 

     System.exit(0); 
    } 

    private static void runWhile() { 
     String username = null; 
     while ((username = getUsername()) != null) { 
      // Use username to complete my logic 
     } 
    } 

    /** 
    * This method locks ResultSet rs until the String username is retrieved. 
    * This prevents skipping the rows 
    * @return 
    * @throws SQLException 
    */ 
    private synchronized static String getUsername() throws SQLException { 
     if(rs.next()) { 
      return rs.getString(1).trim(); 
     } 
     else 
      return null; 
    } 
} 

​​の正しい使い方ですか? ResutSetをロックして他のスレッドが干渉しないことを確認しますか?

これは良いアプローチですか?

+3

私は、ExecutorServiceにタスクを追加するResultSetを読み取るスレッドを1つ持っています。 –

+0

ありがとうございます。私のアプローチが間違っていると感じました。それは動作しますが、それは右感じていません –

+0

それはこのように動作します。しかし、注文は保証されていません。 – gba

答えて

5

JDBCオブジェクトはスレッド間で共有しないでください。これは、Connections、Statements、およびResultSetsに適用されます。ここでの最良のケースは、JDBCベンダが仕様に準拠しており、内部ロックを行うことができるため、すべてのスレッドが同じロックを取得しようとしており、一度に1つしか進捗できない場合です。単一のスレッドを使用するよりも時間がかかります。これは、データベースから読み取るのと同じ作業を行う上で、すべてのスレッドを管理することにより余分なオーバーヘッドが発生するためです。

(ドライバのロックはドライバにとって有益なので、プロバイダはソフトウェアの不正使用による競合状態のバグレポートに対処する必要はありません。

マルチスレッドは、スレッドが同時に進行することができる場合に機能します。Amdahl's Lawを参照してください。 ResultSetを読み込んで結果を使用してExecutorServiceに提出するタスクを作成することができれば(Peter Lawreyがコメントで推薦するように)、それはより意味をなさないでしょう(それらのタスクが独立して動作し、お互いに待たなければならない)。

0

ResultSetを作成し、すべてのデータをDTO(データ転送オブジェクト)またはDAO(データアクセスオブジェクト)にコピーすることをお勧めします。 DTOまたはDAOにデータを格納したら、ResultSet、StatementおよびConnectionを閉じます。

非常に単純な順序でレコードを格納するためにDTO/DAOをクリートする構造、そのフィールド、および機能を解析すると、このです:

ArrayList<HashMap<String, Object>> table = new ArrayList<HashMap<String, Object>>(); 
HashMap<String, Object> record = new HashMap<String, Object>(); 
String field1 = "something"; 
Integer field2 = new Integer(45); 
record.put("field1", field1); 
record.put ("field2", field2); 
table.add(record); 

あなたは(そしておそらくあなたがすべき)/ DTOを自動化して行うことができますDAOは、ハードコードや固定名なしで、どのテーブルでも同じクラスを使用するのに十分な柔軟性を備えています。

ラッパーとデータの格納/読み取りメソッドを作成する必要があり、これらのメソッドはスレッドセーフである必要があることに注意してください。

このデザインは、ResultSetのすべてのレコードを格納するのに十分なメモリがある場合にのみ機能します。

関連する問題