feat: changed implementation to fixed thread pool

This commit is contained in:
Yannik Bretschneider 2021-06-06 17:45:41 +02:00
parent 21bfac7d75
commit 2acf340482

View File

@ -1,13 +1,17 @@
package uulm.teamname.marvelous.server.lobbymanager; package uulm.teamname.marvelous.server.lobbymanager;
import org.tinylog.Logger; import org.tinylog.Logger;
import uulm.teamname.marvelous.server.Server;
import uulm.teamname.marvelous.server.lobby.Lobby;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/** /**
* Class meant for running lobbies. It manages said lobbys, creates threads for it, and moves it into an executor * Class meant for running lobbies. It manages said lobbys, creates threads for it, and moves it into an executor
@ -24,56 +28,59 @@ public class LobbyRunner {
} }
private final HashMap<LobbyConnection, Thread> activeLobbies; private final ExecutorService lobbyExecutor;
private final HashSet<LobbyConnection> activeLobbies;
private LobbyRunner() { private LobbyRunner() {
this.activeLobbies = new HashMap<>(); this.lobbyExecutor = Executors.newFixedThreadPool(Server.getMaxLobbies());
this.activeLobbies = new HashSet<>();
}
boolean canAddLobby() {
return activeLobbies.size() <= Server.getMaxLobbies();
} }
/** Starts a new thread for the current LobbyConnection, and adds it to the currently active lobbies */ /** Starts a new thread for the current LobbyConnection, and adds it to the currently active lobbies */
void startLobby(LobbyConnection connection) { void startLobby(LobbyConnection connection) {
Logger.trace("Starting lobby connection thread '{}'", connection.gameID); Logger.trace("Starting lobby connection thread '{}'", connection.gameID);
synchronized (activeLobbies) { if (activeLobbies.contains(connection)) {
if (activeLobbies.containsKey(connection)) { Logger.warn("Already active lobby was started again. This is probably a bug.");
Logger.warn("Already active lobby was started again. This is probably a bug."); } else if (!canAddLobby()) {
} else { Logger.warn("Scheduling lobby to be started while no thread is free. This might be a bug.");
Logger.trace("Creating lobby thread 'Lobby-{}'...", connection.gameID); activeLobbies.add(connection);
var lobbyThread = new Thread(connection, "Lobby-" + connection.gameID); lobbyExecutor.execute(connection);
Logger.trace("Creating mapping from LobbyConnection to newly created thread");
activeLobbies.put(connection, lobbyThread);
Logger.debug("Starting new lobby thread '{}'", lobbyThread.getName());
lobbyThread.start();
}
}
}
/** Calls {@link Thread#notify()} on the given lobbyConnection's thread */
void notifyLobby(LobbyConnection toNotify) {
var lobbyThread = activeLobbies.get(toNotify);
if (lobbyThread == null) {
Logger.warn("Tried to notify non-existent lobby thread. This is probably a bug.");
} else { } else {
lobbyThread.notify(); Logger.trace("Executing LobbyThread 'Lobby-{}'...", connection.gameID);
activeLobbies.add(connection);
lobbyExecutor.execute(connection);
} }
} }
void removeLobby(LobbyConnection lobby) { void removeLobby(LobbyConnection lobby) {
synchronized (activeLobbies) { synchronized (activeLobbies) {
var lobbyThread = activeLobbies.get(lobby); if (!activeLobbies.contains(lobby)) {
if (lobbyThread == null) {
Logger.warn("Tried to remove non-existent lobby thread. This is probably a bug."); Logger.warn("Tried to remove non-existent lobby thread. This is probably a bug.");
} else { } else {
Logger.debug("Stopping and removing lobby '{}'", lobby.gameID); Logger.debug("Stopping and removing lobby '{}'", lobby.gameID);
lobby.terminateConnection(); lobby.terminateConnection();
lobbyThread.notify();
activeLobbies.remove(lobby); activeLobbies.remove(lobby);
} }
} }
} }
boolean isStarted(LobbyConnection connection) {
return activeLobbies.contains(connection);
}
/** Shutdown all threads, destroy the lobbies, and close everything up */ /** Shutdown all threads, destroy the lobbies, and close everything up */
void shutdownAll() { void shutdownAll() {
Logger.info("Stopping and removing all LobbyThreads"); Logger.info("Stopping and removing all LobbyThreads");
activeLobbies.keySet().forEach(this::removeLobby); activeLobbies.forEach(LobbyConnection::terminateConnection);
try {
lobbyExecutor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
lobbyExecutor.shutdownNow();
} }
} }