2009-10-02 33 views

回答

17

我會退後一步深入重新考慮設計。爲什麼你要在兩個線程之間共享相同的Statement(因此隱含地也是Connection)?

正常JDBC的做法是,你應該獲得和關閉ConnectionStatementResultSet最短可能範圍。也就是說,在同一個方法塊內。這裏有一個基本的例子:

public void update(List<Item> items) throws SQLException { 
    Connection connection = null; 
    PreparedStatement statement = null; 
    try { 
     connection = database.getConnection(); 
     statement = connection.prepareStatement(sql); 
     for (Item item : items) { 
      statement.setObject(1, item.getSomething()); 
      statement.addBatch(); 
     } 
     statement.executeBatch(); 
    } finally { 
     if (statement != null) try { statement.close(); } catch (SQLException ignore) {} 
     if (connection != null) try { connection.close(); } catch (SQLException ignore) {} 
    } 
} 

如果你只想提高連接性能,那麼使用連接池。例如C3P0。但當然要做不是線程之間共享昂貴的數據庫資源!這樣你也不用擔心線程安全問題。這是一個實現細節。

噢,如果還不清楚的話:你會不是通過在多個線程之間共享相同的語句和連接來提高數據庫性能。更糟糕的是,它只會放緩,你會在Java和數據庫端遇到線程安全問題。

+0

我有50多個線程從數據庫讀取大量「鍵」,計算值並更新相應的行。我在一個單獨的線程中調用executeBatch(),現在修改它,以便在executeBatch()正在進行時爲其他線程創建一個新的PreparedStatement。 我只是問這個問題,因爲這個問題的原始答案是誤導。 – palindrom

+3

考慮放置一個工作隊列,其中50+個線程添加行更新,1個消耗線程獲取發出'addBatch()'和'executeBatch()'調用的更新。 – rsp

+0

@rsp有正確的答案,解讀讀取和處理更新。 –

6

是的。根據JDBC規範,所有的JDBC驅動程序實現必須是線程安全的:

Compliance with the JDBC 3.0 API, section A.1.6


如果我理解正確的BalusC的迴應您的意見,您是通過ResultSet從一個聲明迭代,並與操作其他PreparedStatements在一個單獨的線程中同時更新其他行。這不一定要工作(它又取決於JDBC驅動程序,但與線程安全性沒有直接關係)。我不確定最新的版本,但是較早的Oracle JDBC驅動程序例如不支持多條語句,當然不會失敗,但會產生意想不到的結果。如果我沒有記錯,在第一條語句中遍歷結果集時在連接上創建第二條語句會導致第一條語句靜靜地關閉,並且第一個結果集僅返回已從數據庫中獲取的行,儘管更多的行可能已經可用。您的實現聽起來很相似,並且可能會顯示類似的行爲,也與其他數據庫一樣

+0

@jambjo:是的,我正在更新行,因爲我選擇它們。但是在調用executeBatch之前創建一個新的PreparedStatement解決了我的問題。 – palindrom

2

PreparedStatement不強制執行類使這些方法線程安全。所以很明顯這取決於實施課程。

對於前: -DelegatingPreparedStatement是有這些方法,但這些都不是線程安全的,而「OraclePreparedStatement」也有這些方法,而這些都是線程安全的。

3

正如jambjo指出的那樣,規範要求線程安全。但是,正如Rakesh Juyal指出的那樣,在實踐中無法確保這種安全。因此,如果您想要真正實現可移植性和健壯性,請儘可能避免多線程訪問變量,除非您確定您使用的驅動程序符合規範。

至於addBatch和executeBatch,在某些情況下,這些方法本身並不可靠。我知道,每當我嘗試將這些與Oracle驅動程序(單線程)結合使用時,我都會得到不可預知的結果。所以,線程安全不是你的問題,而是批量。

1

它可能非常適合JDBC供應商。我寧願永遠不要依賴對批處理的併發訪問,並將併發的複雜性委託給數據庫服務器。爲什麼不建立更多的獨立連接?

相關問題