我在JavaFX中編寫了一個(gè)格鬥遊戲,使用JDBC將資訊更新到MySQL資料庫。如果不重複連續(xù)執(zhí)行,從資料庫伺服器取得基本資訊的大多數(shù)任務(wù)都能正常運(yùn)作。問題出現(xiàn)在我需要程式不斷更新對(duì)手的訊息,例如遊戲中的位置、等級(jí)、傷害等。我必須不斷向伺服器發(fā)送select命令,這會(huì)增加執(zhí)行這些命令的執(zhí)行緒使用的RAM。
void startUpdatingOpponentInfo() { Thread thread = new Thread(() -> { while (matchID != -1) { String query = String.format("select * from matchDetails where matchID = %d and userID = %d", matchID, opponentID); try { ResultSet resultSet = sqlConnection.getDataQuery(query); while (resultSet.next()) { double opponentX = resultSet.getDouble("xPos"); double opponentY = resultSet.getDouble("YPos"); if (opponentX != -1 && opponentY != -1) opponent.move(canvas, new Position(opponentX, opponentY)); } } catch (SQLException e) { e.printStackTrace(); } try { Thread.sleep(10); } catch (InterruptedException e) { throw new RuntimeException(e); } } }); } public ResultSet getDataQuery(String query) { Statement statement; ResultSet resultSet = null; try { statement = connection.createStatement(); resultSet = statement.executeQuery(query); } catch (SQLException e) { System.out.println(query); e.printStackTrace(); } return resultSet; }
我嘗試搜尋了一些方法,找到了一個(gè)非常有用的方法。在每個(gè)select之後,我會(huì)讓線程休眠一段時(shí)間,然後再進(jìn)行select。這種方式顯著提高了效能,RAM的消耗量保持穩(wěn)定。然而,對(duì)於需要始終刷新的查詢資訊來說,這種方法並不適用,因?yàn)椤竤elect」執(zhí)行緒的短暫休眠仍然會(huì)導(dǎo)致RAM消耗較高。是否有任何有用的方法可以解決這個(gè)問題,讓我的遊戲直接連接到資料庫伺服器,而不經(jīng)過中間遊戲伺服器。
你應(yīng)該先嘗試優(yōu)化你的變數(shù)。
你的執(zhí)行緒在查詢時(shí)一直使用新的String,但實(shí)際上它只需要建置一次。同樣,對(duì)於你的ResultSet,在每次進(jìn)入新的循環(huán)時(shí),你都會(huì)在RAM中使用一個(gè)新的位置來儲(chǔ)存一個(gè)新的物件。
你可以透過在Java ID物件之外加入一個(gè)控制臺(tái)輸出來檢查:
System.out.println(resultSet);
然後觀察每次輸出的結(jié)果是不是不同。
像這樣:
Thread thread = new Thread(() -> { ResultSet resultSet; final String query = String.format("select * from matchDetails where matchID = %d and userID = %d", matchID, opponentID); while (matchID != -1) { try { resultSet = sqlConnection.getDataQuery(query);
然後我讓你考慮改變你的查詢,只選擇xPos/yPos不等於"-1"的值,並且只獲取真正的對(duì)手位置變化的結(jié)果,最後,也許不發(fā)送一個(gè)"new Position",而只發(fā)送兩個(gè)變數(shù)opponentX和opponentY,這樣可以避免將這個(gè)物件儲(chǔ)存在RAM中。
不要忘記,Java只會(huì)在程式碼執(zhí)行完成後清理你的RAM物件(簡而言之),所以擁有一個(gè)永不結(jié)束的單一執(zhí)行緒不會(huì)觸發(fā)這種情況。