2009-08-01 6 views
3

私は一定の間隔でデータベースにクエリを行うプログラムを持っており、呼び出したレコードで何らかのアクションを実行してからテーブルを再度更新します。JDBCとスレッディング

ExecutorServiceを使用してスレッドを実行していますが、各スレッドが(データベースを更新する必要があるため)独自の接続を取得する必要がありますか、初期の結果を照会するのに使用した接続と同じ接続を使用できますか?

接続プーリングの作業は、Oracle 9iで可能です。

答えて

10

この方法でドライバがスレッドセーフではないため、別々のスレッドには常に別の接続を使用する必要があります。接続プールは安全な方法で接続の再利用を可能にするので、あなたを助けることができます。

あなたが問題を正しく理解していれば、あるスレッドがクエリを担当し、データベースを更新する可能性のあるN個のスレッドを開始するクエリディスパッチパターンを実行することもできます。

スレッドは次の構造使用して、行とテーブルのロックの面で互いにつまずくはありませんので、あなたはまた、PreparedStatementのを経由してバッチ更新を行うことを検討可能性があります

  • 1クエリスレッドを
  • NCPU処理スレッドミニDBフォーク参加同様
  • 1バッチ更新スレッド

編集てpstmtとバッチ更新を行う方法について

例:

PreparedStatement pstmt = connection.prepareStatement(
    "UPDATE table SET field=? WHERE id=?"); 
for (int i = 0; i < 100; i++) { 
    pstmt.setInt(1, i * i); 
    pstmt.setInt(2, i); 
    pstmt.addBatch(); 
} 
pstmt.executeBatch(); 
pstmt.close(); 

それとも、更新要求が処理スレッドから到着ループでのキューを照会できます。

class WhatToUpdate { 
    public int id; 
    public int value; 
} 
Queue<WhatToUpdate> queue = new LinkedBlockingQueue<WhatToUpdate>(); 

PreparedStatement pstmt = connection.prepareStatement(
    "UPDATE table SET field=? WHERE id=?"); 

int poisons = THE_NUMBER_OF_PROCESSING_THREADS; 
while (true) { 
    WhatToUpdate record == queue.take(); 
    if (record == null) { // poison pill 
     if (--poisons <= 0) { 
      break; 
     } 
    } 
    pstmt.setInt(1, record.value); 
    pstmt.setInt(2, record.id); 
    pstmt.addBatch(); 
} 
pstmt.executeBatch(); 
pstmt.close(); 
+0

ありがとうございます! 私は処理のために1つのクエリスレッドとN個のスレッドを持っています。準備されたステートメントを使用してバッチ更新を行うにはどうすればよいですか? – Ngetha

+0

ありがとう、これは完全に私のために働いた – Ngetha

+0

@ Ngetha:これはあなたの質問に答えた場合は、*受け入れる*答え:http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work(他の質問にも同じことが起こります。) –

2

Oracle jdbc OracleConnectionおよびOraclePreparedStatementのコードを見ると、m重要なメソッドの中で同期されているので、スレッドセーフです。 1つのConnectionを複数のスレッドに渡って使用しても、それぞれのスレッドは、独自のアクションを実行する前に、ConnectionおよびPreparedStatement(特に)の操作を完了するまで待機する必要があるため、

+1

@akf:質問にはOracle 9iが特に言及されていますが、実装固有の動作に依存することはお勧めできません。確かに、他のベンダーのJDBCスタックがスレッドセーフであるという保証はありません。 AFAIKでは、JDBC仕様では必須ではありません。 –

+0

@Stephen C、良い点。 – akf

+0

PreparedStatement APIスレッドを安全にすることはできません。すべてのメソッドを同期させることでスレッドを安全にすることはできません。これはステートフルなAPIです。一般にPreparedStatementインスタンスにスレッド間で安全にアクセスできるようにするには、APIを再設計する必要があります。 –

関連する問題