2010-04-26 104 views
7

我還是一名剛從事兼職工作的本科生,所以我一直在努力去注意更好的方式來做事情。最近,我不得不寫一個工作程序,程序的主線程會產生「任務」線程(對於每個數據庫「任務」記錄),這些線程將執行一些操作,然後更新記錄以表明它已完成。因此,我需要一個數據庫連接對象和ThreadedTask對象中可用的PreparedStatement對象。Java中的Thread中PreparedStatements的這種用法是否正確?

這大概是我最後寫的,是爲每個線程創建一個PreparedStatement對象嗎?我想靜PreparedStatments可以創造競爭條件...

 
Thread A stmt.setInt(); 
Thread B stmt.setInt(); 
Thread A stmt.execute(); 
Thread B stmt.execute(); 

A's版本永遠不會被execed ..

這是線程安全的?正在創造和銷燬永遠不變的巨大垃圾?

public class ThreadedTask implements runnable { 
    private final PreparedStatement taskCompleteStmt; 

    public ThreadedTask() { 
     //... 
     taskCompleteStmt = Main.db.prepareStatement(...); 
    } 

    public run() { 
     //... 
     taskCompleteStmt.executeUpdate(); 
    } 
} 

public class Main { 
    public static final db = DriverManager.getConnection(...); 
} 
+2

不要存儲連接,在需要時獲取連接。 如果您需要bettr性能,請使用連接池。 AS Thilo如下所述,不會在線程之間分享內容。 – 2010-04-26 12:41:41

回答

16

我認爲在線程之間共享數據庫連接(和預處理語句)並不是一個好主意。 JDBC不要求連接是線程安全的,我希望大多數驅動程序不會。

爲每個線程提供自己的連接(或者在連接上爲每個查詢進行同步,但這可能會破壞具有多個線程的目的)。

正在創建和銷燬始終相同的PreparedStatement對象不是一個巨大的浪費?

不是。大多數工作發生在服務器上,並且如果使用相同的SQL語句,則會在那裏被緩存和重用。某些JDBC驅動程序也支持語句緩存,因此即使客戶端語句句柄也可以重新使用。

雖然使用批量查詢而不是多線程(或除此之外),您可以看到實質性改進。準備一次查詢,並在單個大批量中運行大量數據。

3

您最好使用連接池並讓每個線程從池中請求連接。在你交給你的連接上創建你的語句,記住關閉它,等你完成後再釋放它回到池中。使用池的好處是,如果發現線程併發性成爲問題,您可以輕鬆增加可用連接的數量。

6

threadsafety在這裏不是問題。所有外觀在語法上和功能上都很好,它應該可以工作大約半個小時。然而,資源的泄漏是這裏真正的問題。大約半小時後,應用程序會崩潰,因爲您在使用後永遠不會關閉它們。數據庫反過來遲早會關閉連接本身,以便它可以聲稱返回。

這就是說,你不需要擔心緩衝已準備好的狀態。 JDBC驅動程序和數據庫將關注此任務。而不必擔心資源泄漏,並儘可能使JDBC代碼儘可能實用。

public class ThreadedTask implements runnable { 
    public run() { 
     Connection connection = null; 
     Statement statement = null; 
     try { 
      connection = DriverManager.getConnection(url); 
      statement = connection.prepareStatement(sql); 
      // ... 
     } catch (SQLException e) { 
      // Handle? 
     } finally { 
      if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {} 
      if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {} 
     } 
    } 
} 

爲了提高連接性能,使用連接池的像c3p0(這樣的方式並不意味着你可以改變你如何編寫JDBC代碼的方法;始終獲得在關閉資源在try-finally區塊中的最短可能範圍)。

+1

看一看Apache Commons DBUtils的輕量級包裝,照顧所有的嘗試/捕獲。 – Thilo 2010-04-26 12:49:41

+0

我們也可以只使用JPA。更方便不可能。 – BalusC 2010-04-26 12:53:07

+0

如果您使用Java 7+:更喜歡使用「嘗試使用資源塊」。在這種情況下,你不能忘記關閉連接和聲明。 – 2016-05-10 15:26:51

相關問題