I'm upgrading my python websocket game server to Java, (using Jetty for websockets), and recently started to learn about thread safety.
My challenge is, the game logic (gameRoom instance) runs on the main thread, but the server will be receiving player messages (eg. a message to join a game room), and notifying the game logic FROM ANOTHER THREAD. I originally (in python-when all was on the main thread) just processed the message right away, (eg. add a player on recieving a message). This can lead to problems with multiple threads, as the gameRoom thread might be adding a player at the same time, to the players array. (The players list ends up being shared during adding a player= not thread safe!)
What's the SIMPLEST way to handle recieving messages from a servlet running on it's own threads, and process these messages WITHOUT messing up the game running on the main thread(a different thread)? In my head, i'd imagine some kind of one-way buffer (eg. http://web.mit.edu/6.005/www/fa14/classes/20-queues-locks/message-passing/) to queue new messages to be processed ONLY by the gameRoom itself, during part of the logic. Or is there a way to avoid mulitple threads at all!? *Please give your thoughts, I'd love to hear from someone with more than my begginner level of thread knowledge. I greatly appreciate all tips/ advice :) *
I took the time to make a SIMPLE EXAMPLE showing what's going on (please ignore synax errors, i made it super short for your convinience :) ):
class ServerClass {
static GameRoomClass gameRoom;
static void main() {
//psuedocode start Jetty Server, this server runs in another thread, will call onServerMessage()
jettyServer.start();
jettyServer.onMessageCallback=(onServerMessage); //set message callback (pseudocode)
//create game room, run on main thread
gameRoom = GameRoomClass();
gameRoom.runGameRoom();
}
//when the server gets a message from a player,
//this will be called by the server from another thread, will affect the GameRoom
static void onServerMessage(Message theMessage) {
gameRoom.gotServerMessage();
}
}
//this runs game logic
class GameRoomClass {
ArrayList<E> players = new ArrayList<>();
public void runGameRoom() {
while (true) {
//move players, run logic...
//sometimes, may call addNewPlayer AS WELL
if(...){
addNewPlayer();
}
}
}
public gotServerMessage(){
//this will only be called by the 'Server' thread, but will enter 'addNewPlayer' method
//meaning it will access shared value players?
addNewPlayer()
}
public addNewPlayer(){
//this will be called by the server thread, on getting a message
//can ALSO be called by gameRoom itself
players.add(new PlayerObj());
}
}
class PlayerObj {
//a player in the game
}
The simplest and efficient way is to use one of thread-safe collection classes from java.util.concurrent package. For the given case ConcurrentLinkedQueue seems to be a good start.