На сервере AtomicBoolean завершает работу слишком поздно (Java) - PullRequest
0 голосов
/ 11 апреля 2020

Я работаю над приложением клиент-сервер и хочу завершить работу сервера, когда через сокет получено сообщение об остановке. Код для моего сервера выглядит следующим образом

public class Server extends Thread {

 private AtomicBoolean running = new AtomicBoolean(true);


  public synchronized void setRunning(boolean value){
        running.set(value);
    }

 public void run(){

        while(running.get()){
                try {
                     clientSocket = serverSocket.accept();
                     //doing stuff...

                }catch (IOException e) {
                    logger.error("{} \n",e.getMessage());
                }
        }

Переменная Запуск установлен в другом классе, который обрабатывает мои сообщения. Функция написана следующим образом:

public synchronized void onReceive(Message message){

       if(message.equals(stopMessage)){

           server.setRunning(false);
           for(Client c : clients)
               c.shutdown();
           server.shutdown();
       }
}

Моя проблема в том, что, пока l oop на сервере выполняет еще одну итерацию, прежде чем установить для бегущей переменной значение false, и сервер пытается проверить сокет, даже если это так. null, так как клиент, подключенный к этому сокету, уже закрыт (клиент также является потоком). Я делаю что-то не так, но я не знаю, что. Любые идеи? Спасибо!

1 Ответ

1 голос
/ 11 апреля 2020

Измените while l oop следующим образом:

while( running.get() )
{
    try( clientSocket = serverSocket.accept() ) 
    {
        if( !running.get() ) break;
        //doing stuff...

    }
    catch( SocketTimeoutException e )
    {
        continue;
    }
    catch( SocketException e )
    {
        if( !serverSocket.isClosed() ) logger.error( "{} \n", e.getMessage() );
        break;
    }
    catch( IOException e ) 
    {
        logger.error( "{} \n", e.getMessage() );
        break;
    }
}

l oop ожидает в serverSocket.accept() и будет работать только при входящем соединении или по таймауту. Изменение running не пробуждает его, поэтому оно распознает это изменение только в следующем цикле в while l oop.

И после исключения ошибки не следует продолжать l oop. Даже в случае SocketTimeoutException, continue может быть неправильным / недостаточным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...