我有一個程序,需要在給定的時間間隔內查詢一個數據庫,並用它獲得的記錄調用執行某個動作,然後再次更新表。我正在使用ExecutorService來運行線程,但我想知道,每個線程應該獲得自己的連接(因爲它需要更新數據庫),或者我可以使用我用來查詢初始結果的同一個連接嗎?JDBC和線程
可以連接池工作,在Oracle 9i上。
我有一個程序,需要在給定的時間間隔內查詢一個數據庫,並用它獲得的記錄調用執行某個動作,然後再次更新表。我正在使用ExecutorService來運行線程,但我想知道,每個線程應該獲得自己的連接(因爲它需要更新數據庫),或者我可以使用我用來查詢初始結果的同一個連接嗎?JDBC和線程
可以連接池工作,在Oracle 9i上。
對於單獨的線程,您應該總是使用單獨的連接,因爲驅動程序在這種方式下不是線程安全的。連接池可以幫助您,因爲它可以以安全的方式重新使用連接。
如果我正確理解您的問題,您也可以執行查詢分派模式,其中一個線程負責查詢並啓動N個可能更新數據庫的線程 - 所有這些線程都有單獨的連接對象。
你也可以考慮通過做PreparedStatement的批量更新,所以線程不會在行和表鎖的條款對對方絆倒,採用以下結構:
就像一個小型數據庫的fork-join。如何做批量更新與數PreparedStatement 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();
如果您查看Oracle jdbc OracleConnection
和OraclePreparedStatement
的代碼,請將m許多重要的方法是同步的,所以它們是'線程安全的'。在多個線程中使用單個Connection
不會給您最大的效率,因爲在執行自己的操作之前,每個線程都需要等待Connection
和PreparedStatement
(特別是execute
)的操作完成。
謝謝! 我有一個查詢線程和N個線程進行處理。我如何使用準備好的語句進行批量更新? – Ngetha 2009-08-01 07:28:43
謝謝,這對我很好用 – Ngetha 2009-08-04 05:18:04