多线程IllegalMonitorStateException

时间:2018-05-06 02:17:16

标签: java multithreading swing runtime-error illegalstateexception

我正在编写一个多线程的tic tac toe程序,其中服务器是两个客户端之间的连接。服务器打开并等待连接:第一个连接的客户端是玩家X,第二个是玩家O.玩家可以随时退出游戏,一旦客户端退出,其他客户端将重置其主板并等待新的联系。这部分工作正常,但问题是,一旦我产生了一个新客户端,我会收到以下错误:

  

java.base /中java.base / java.util.concurrent.locks.ReentrantLock $ Sync.tryRelease(ReentrantLock.java:149)中的线程“pool-1-thread-1”java.lang.IllegalMonitorStateException异常java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1300)位于TicTacToeServer.processMessage的java.base / java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:439)(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)在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,它处理客户端发送的消息,部分显示在上面。

我一直在试图关闭连接,输入,输出等,但我似乎无法摆脱这个错误。它不影响实际游戏,我假设因为错误是在关闭的线程上,但我仍然想修复它。任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:0)

来自ReentrantLock.unlock()的{​​{3}}:

  

如果当前线程不是此锁的持有者那么   抛出IllegalMonitorStateException。

您需要在unlock之前获取锁定。