[英]Why does a single thread make my Java Program so much faster?
我的任務是創建一個 sql 數據庫並在 Java 中創建一個 GUI 來訪問它。 我幾乎擁有它,但我有一個關於線程的問題。 在今天之前,我沒有在我的程序中使用任何線程,結果只是從數據庫中提取 150 條記錄,我不得不等待大約 5 到 10 秒。 這很不方便,我不確定是否可以解決這個問題。 今天我在互聯網上查看了在類似於我的程序中使用線程的信息,我決定在這種方法中只使用一個線程:
public Vector VectorizeView(final String viewName) {
final Vector table = new Vector();
int cCount = 0;
try {
cCount = getColumnCount(viewName);
} catch (SQLException e1) {
e1.printStackTrace();
}
final int viewNameCount = cCount;
Thread runner = new Thread(){
public void run(){
try {
Connection connection = DriverManager.getConnection(getUrl(),
getUser(), getPassword());
Statement statement = connection.createStatement();
ResultSet result = statement.executeQuery("Select * FROM "
+ viewName);
while (result.next()) {
Vector row = new Vector();
for (int i = 1; i <= viewNameCount; i++) {
String resultString = result.getString(i);
if (result.wasNull()) {
resultString = "NULL";
} else {
resultString = result.getString(i);
}
row.addElement(resultString);
}
table.addElement(row);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
};
runner.start();
return table;
}
我真正改變的唯一一件事是添加了線程“跑步者”,性能呈指數級增長。 以這種方式幾乎可以立即提取 500 條記錄。
該方法之前看起來像這樣:
public Vector VectorizeTable(String tableName) {
Vector<Vector> table = new Vector<Vector>();
try {
Connection connection = DriverManager.getConnection(getUrl(),
getUser(), getPassword());
Statement statement = connection.createStatement();
ResultSet result = statement.executeQuery("Select * FROM "
+ tableName);
while (result.next()) {
Vector row = new Vector();
for (int i = 1; i <= this.getColumnCount(tableName); i++) {
String resultString = result.getString(i);
if (result.wasNull()) {
resultString = "NULL";
} else {
resultString = result.getString(i);
}
row.addElement(resultString);
}
table.addElement(row);
}
} catch (SQLException e) {
e.printStackTrace();
}
return table;
}
我的問題是為什么有線程的方法比沒有線程的方法快得多? 我不在程序中的任何地方使用多個線程。 我在網上看過,但似乎沒有任何答案可以回答我的問題。
任何人都可以提供的任何信息將不勝感激。 我是線程 XO 的菜鳥
如果您需要任何其他附加信息來幫助了解正在發生的事情,請告訴我!
回答:
看看 Aaron 的回答,這根本不是線程問題。 我現在覺得很無聊:(。謝謝@Aaron!
我認為您所做的似乎使數據庫加載更快,因為VectorizeView
方法在數據加載之前返回。 然后加載在后台進行,並在(可能)與以前相同的時間完成。
您可以通過在 thread.start() 調用之后添加thread.join()
thread.start()
來測試這個理論。
如果發生這種情況,您可能需要在加載完成之前阻止應用程序的其他部分訪問table
object。 否則,如果用戶在啟動后過早執行某些操作,您的應用程序可能會出現錯誤行為。
FWIW,從數據庫加載 100 或 500 條記錄應該很快,除非查詢本身對數據庫來說很昂貴。 對於表格中的簡單 select 不應該是這種情況......除非您實際上是從視圖而不是表格中選擇,並且該視圖設計不佳。 無論哪種方式,您可能最好關注為什么這樣一個簡單的查詢需要這么長時間,而不是嘗試在單獨的線程中運行它。
在您的跟進中,您說start
后加入的版本與沒有join
的版本一樣快。
我的第一反應是說:“把join
留在那里。你已經解決了問題。”
但這並不能解釋實際發生了什么。 我現在完全困惑了。 我能想到的最好的事情是您的應用程序在此之前在當前線程上所做的事情是造成這種情況的原因。
也許您應該調查在發生這種情況期間應用程序正在做什么。 看看你是否能弄清楚所有的時間都花在了哪里。
看起來您啟動(即start
)一個后台線程來執行查詢,但您沒有join
等待計算完成。 當您返回table
時,它不會被查詢的結果填充 -在您的方法返回后,另一個線程會隨着時間的推移填充它。 該方法幾乎立即返回,因為它沒有做任何實際工作。
如果要確保在方法返回之前加載數據,則需要調用runner.join()
。 如果這樣做,您將看到加載數據所花費的時間與以前一樣長。 與新代碼的唯一區別是工作在單獨的執行線程中執行,允許您的代碼的 rest 繼續執行它需要執行的其他工作。 請注意,如果主線程中的代碼在后台線程實際填充之前嘗試使用 Vector 中的數據,則調用join
失敗可能會導致錯誤。
更新:我剛剛注意到您還在多線程版本中預先計算getColumnCount
,而在單線程版本中,您正在為內部循環的每次迭代計算它。 根據該方法的復雜性,這可能解釋了部分加速(如果有的話)。
你確定它更快嗎? 由於您啟動單獨的線程,您將立即返回table
。 但是,您確定在數據完全填充后測量時間嗎?
更新要正確測量時間,請將runner
object 保存在某處並調用runner.join()
。 你甚至可以對它以同樣的方法進行測試。
好的,我認為如果您在此方法結束時檢查table
,您會發現它是空的。 這是因為start
開始在后台運行線程,並且您立即返回 table,而后台線程沒有機會填充它。 所以看起來速度更快,但實際上並非如此。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.