Как остановить поток, ожидающий ввода - PullRequest
0 голосов
/ 24 августа 2018

В моей программе есть поток прослушивателя, который просто ожидает ввода с сервера.Поэтому он получает сообщение, ставит его в очередь и ждет другого.Из-за этого факта его нельзя закрыть способом, предложенным в других аналогичных темах, поскольку ему необходимо получить сообщение от сервера перед проверкой условия «Пока».

Вот оно:

public class Listener implements Runnable{

    private Socket socket; 
    private ObjectInputStream ois;


    public Listener(Socket socket) {
        this.socket = socket;
        try {
            this.ois = new ObjectInputStream(socket.getInputStream());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void run() {
        try {
            while(!socket.isClosed()) {
                String type = ois.readUTF();
                System.out.println("received: " +type);
                main.queue.put(type);
            }
        } catch (IOException | InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Итак, в основном, когда я закрываю сокет, ois.readUTF генерирует исключение EOFException.Что я могу сделать, чтобы правильно остановить этот поток без получения этого исключения?

Единственный найденный мной способ - когда клиент хочет прервать соединение (и, таким образом, закрыть сокет), он может отправить сообщение на сервер (например, «до свидания» или что-то в этом роде), а затем на сервер.также ответит "до свидания", и когда мой слушатель получит это до свидания, он закроет сокет, который заставит его выйти из цикла while и остановиться.Я думаю, что это должно работать хорошо.Но я хотел бы знать, есть ли другой способ сделать это (почему-то я не очень доволен своей идеей).

1 Ответ

0 голосов
/ 24 августа 2018

Лучший способ сделать это - использовать неблокирующий IO API, предоставляемый NIO API . Это потребует внесения нетривиальных изменений в этот фрагмент кода.

Самый простой способ - установить флаг isFinishing перед закрытием сокета. Затем ожидающий поток должен проверить, установлен ли флаг в предложении catch. Если это так, то он может спокойно игнорировать EOFException. Если вы идете этим путем, убедитесь, что isFinishing правильно синхронизирован (либо энергозависим, либо лучше a CountDownLatch).

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