Я пишу многопоточную программу крестики-нолики, в которой сервер - это соединение между двумя клиентами. Сервер открывается и ожидает подключения: первый клиент для подключения - это игрок X, а второй - игрок O. Игроки имеют возможность выйти из игры в любой момент, и как только клиент выходит из игры, другой клиент сбрасывает свою доску и ждет новое соединение. Эта часть работает нормально, но проблема в том, что как только я создаю нового клиента, я получаю следующие ошибки:
Exception in thread "pool-1-thread-1" java.lang.IllegalMonitorStateException at java.base/java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:149) at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1300) at java.base/java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:439) at TicTacToeServer.processMessage(TicTacToeServer.java:329) at TicTacToeServer$Player.run(TicTacToeServer.java:498) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:844)
Похоже, что именно тот поток, который был закрыт, вызывает эту ошибку. Игрок X всегда является тем клиентом, который подключается первым, поэтому это всегда поток 1, в то время как игрок O всегда поток 2. Из-за указанной выше ошибки я закрыл игрока X и открыл новый (поток 3).
В каждом клиентском окне есть кнопка, позволяющая им выйти, которая использует прослушиватель действий, созданный, как показано:
quitGame = new JButton("Quit");
quitGame.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Quit button was clicked!");
displayMessage( "You have quit the game.\n" );
output.format("Quit. " + myMark + "\n");
output.flush();
try
{
connection.close(); // close connection to client
System.exit(0);
} // end try
catch ( IOException ioException )
{
ioException.printStackTrace();
System.exit( 1 );
} // end catch
}
});
panel2.add( quitGame, BorderLayout.SOUTH ); // add button to panel
add( panel2, BorderLayout.CENTER ); // add container panel
Это соответствует следующему коду на сервере:
else if (message.equals("Quit. X")) {
//connection.close(player[PLAYER_X]);
currentPlayer = PLAYER_X;
displayMessage("\nPlayer X has ended the game.\n");
players[1].send("Player X has ended the game.");
players[1].send("Please wait for new player to connect.");
players[(currentPlayer+1)%2].send("Restart.");
players[currentPlayer].send("Restart.");
for(int x = 0;x<board.length;x++)
{
board[x] = "";
numRep[x] = 4;
}// end for loop
try // wait for connection, create Player, start runnable
{
players[ 0 ] = new Player( server.accept(), 0 );
Player temp = players[0];
players[1].send("New player has connected. Game on!");
players[1].send("Please wait for your turn.");
runGame.execute( players[0] ); // execute player runnable
} // end try
catch ( IOException ioException )
{
ioException.printStackTrace();
System.exit( 1 );
} // end catch
//gameLock.lock();
try // allow x to go first
{
players[ PLAYER_X ].setSuspended( false ); // resume player X
otherPlayerConnected.signal(); // wake up player X's thread
} // end try
finally
{
gameLock.unlock(); // unlock game after signaling player X
} // end finally
} // end if
В сообщении об ошибке упоминаются следующие строки:
gameLock.unlock(); // unlock game after signaling player X
который показан в блоке finally выше и
if ( input.hasNextLine() )
processMessage(input.nextLine()); // get message
Это находится в run () и вызывает processMessage, который обрабатывает сообщения, отправленные клиентом, и частично показан выше.
Я пытался возиться с закрытием соединения, ввода, вывода и т. д., Но я не могу избавиться от этой ошибки. Я предполагаю, что это не влияет на саму игру, потому что ошибка связана с закрытым потоком, но я все же хотел бы ее исправить. Любая помощь приветствуется!




Из докReentrantLock.unlock():
If the current thread is not the holder of this lock then IllegalMonitorStateException is thrown.
Вам необходимо приобрести замок до unlock.
Новый тред / плеер или тот, который закрыт? Также как мне получить блокировку? Я думал, это просто для игры