我在JavaFX中編寫了一個格鬥遊戲,使用JDBC將資訊更新到MySQL資料庫。如果不重複連續執行,從資料庫伺服器取得基本資訊的大多數任務都能正常運作。問題出現在我需要程式不斷更新對手的訊息,例如遊戲中的位置、等級、傷害等。我必須不斷向伺服器發送select命令,這會增加執行這些命令的執行緒使用的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; }
我嘗試搜尋了一些方法,找到了一個非常有用的方法。在每個select之後,我會讓線程休眠一段時間,然後再進行select。這種方式顯著提高了效能,RAM的消耗量保持穩定。然而,對於需要始終刷新的查詢資訊來說,這種方法並不適用,因為「select」執行緒的短暫休眠仍然會導致RAM消耗較高。是否有任何有用的方法可以解決這個問題,讓我的遊戲直接連接到資料庫伺服器,而不經過中間遊戲伺服器。
你應該先嘗試優化你的變數。
你的執行緒在查詢時一直使用新的String,但實際上它只需要建置一次。同樣,對於你的ResultSet,在每次進入新的循環時,你都會在RAM中使用一個新的位置來儲存一個新的物件。
你可以透過在Java ID物件之外加入一個控制台輸出來檢查:
然後觀察每次輸出的結果是不是不同。
像這樣:
然後我讓你考慮改變你的查詢,只選擇xPos/yPos不等於"-1"的值,並且只獲取真正的對手位置變化的結果,最後,也許不發送一個"new Position",而只發送兩個變數opponentX和opponentY,這樣可以避免將這個物件儲存在RAM中。
不要忘記,Java只會在程式碼執行完成後清理你的RAM物件(簡而言之),所以擁有一個永不結束的單一執行緒不會觸發這種情況。