[英]Java multithreading and connection pooling with PreparedStatement
[英]connection pooling timeout problems in multithreading environment
我的團隊必須進行一些更改並更新舊的Web應用程序。 該應用程序具有一個主線程和5至15個守護程序線程,這些線程用作工作程序以在DB中檢索和插入數據。
所有這些線程都具有這種設計(為方便起見,此處進行了簡化):
public MyDaemon implements Runnable {
// initialization and some other stuffs
public void run() {
...
while(isEnabled) {
Engine.doTask1();
Engine.doTask2();
...
Thread.sleep(someTime);
}
}
}
Engine類提供了一系列靜態方法,這些方法用於處理DataAccessor類的其他方法,其中一些方法是靜態的:
public Engine {
public static doTask1() {
ThisDataAccessor.retrieve(DataType data);
// some complicated operations
ThisDataAccessor.insertOrUpdate(DataType data);
}
public static doTask2() {
ThatDataAccessor da = new ThatDataAccessor();
da.retrieve(DataType data);
// etc.
}
...
}
DataAccessor類通常使用包含在同步方法中的簡單JDBC語句與DB交互(某些類是靜態的)。 DataSource在服務器中配置。
public ThatDataAccessor {
public synchronized void retrieve(DataType data) {
Connection conn = DataSource.getConnection();
// JDBC stuff
conn.close();
}
...
}
問題是主線程需要連接到數據庫,並且當這些守護程序線程正在工作時,我們很容易用盡池中的可用連接,從而出現“等待連接超時”異常。 此外,有時甚至那些守護程序線程也會獲得相同的異常。
我們必須擺脫這個問題。
我們有一個配置有20個連接的連接池,由於“ 20”是我們的生產環境標准,因此無法添加。 即使我們計划僅將“ synchronized”關鍵字移到真正需要的地方,也需要同步一些代碼塊。 但是我認為這不會真正改變。
我們沒有多線程編程方面的經驗,並且以前從未遇到過連接池問題,這就是為什么我要問: 問題出在這些線程的設計上嗎? 有沒有我們沒有注意到的缺陷?
我已經逐一剖析了線程類,只要它們不是並行運行的,似乎沒有瓶頸可以證明那些“等待連接超時”。 該應用程序使用Oracle 11g在WebSphere 7上運行。
您可能在某個地方丟失了finally塊,無法將連接返回到池中。 使用休眠,我認為這可能在您調用close()時完成,或者對於事務(當您調用rollback()時)完成。 但是我還是會打電話給關閉。
例如,我自己編寫了一個快速且骯臟的池,以擴展一個舊應用程序以使其成為多線程,這是一些處理代碼(除了finnally塊,這對您來說沒有任何意義):
try {
connection = pool.getInstance();
connection.beginTransaction();
processFile(connection, ...);
connection.endTransaction();
logger_multiThreaded.info("Done processing file: " + ... );
} catch (IOException e) {
logger_multiThreaded.severe("Failed to process file: " + ... );
e.printStackTrace();
} finally {
if (connection != null) {
pool.releaseInstance(connection);
}
}
人們無法正確使用finally塊是相當普遍的。例如,看一下這個休眠教程,然后跳到最底層的例子。 您會看到在try {}中他使用了tx.commit(),在catch {}中他使用了tx.rollback(),但是他沒有session.close(),並且最終也沒有。 因此,即使他在try和catch中添加了“ session.close()”,如果他的try塊拋出了RuntimeException以外的東西,或者他的catch在try之前引發了另一個異常,或者在rollback()之前引發了非HibernateException異常,他的聯系不會被關閉。 沒有session.close(),我認為這實際上不是很好的代碼。 但是,即使代碼似乎可以正常工作,最終也可以確保您免受此類問題的侵害。
因此,我將重寫他的使用Session來匹配此休眠文檔頁面上顯示的慣用法的方法。 (而且我也不建議他拋出RuntimeException,但這是一個不同的主題)。
因此,如果您使用的是Hibernate,我認為以上內容就足夠了。 但是否則,如果需要特定的代碼幫助,則需要更加具體,但是否則,您應該使用finally確保連接關閉的簡單想法就足夠了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.