Прерывание потока, который заблокирован в ожидании ввода-вывода из сокета?

У меня есть приложение, которое прослушивает входящие соединения на указанном имени хоста и порту. Прослушивание вызывается с помощью метода listen() (см. ниже), который постоянно ожидает входящего соединения с помощью ServerSocket.accept(), создавая новый Thread для обработки входного потока.

private ServerSocket serverSocket;
private Thread listenerThread;

public void listen() throws IOException {
    this.listenerThread = new Thread(new Runnable() {

        @Override
        public void run() {
            while (true) {
                try {
                    Socket socket = TheServerClass.this.serverSocket.accept();
                    // Create new thread to handle the incoming connection
                }
                catch (IOException exc) { }
            }
        }
    });
    this.listenerThread.start();
}

Теперь я хочу остановить запуск listenerThread. Но когда я вызываю this.listenerThread.interrupt(), это не работает.
Я думал, что поток можно остановить, прервав его, так почему же это не работает?

(Примечание: возможное решение — закрыть ServerSocket с помощью this.serverSocket.close(), но можно ли это сделать с помощью interrupt() или чего-то еще?)


person MC Emperor    schedule 11.01.2012    source источник
comment
Как вы указываете, при использовании стандартных сокетов это возможно только путем закрытия сокета. Здесь есть несколько вопросов о SO, занимающихся одной и той же проблемой, например. stackoverflow .com/questions/1510403/   -  person Peter Štibraný    schedule 11.01.2012
comment
Что вы имеете ввиду под не работает? Выдает ли он какие-либо исключения? Или просто продолжать обычно?   -  person medopal    schedule 11.01.2012
comment
@medopal Поток просто продолжает работать, не прерывая его.   -  person MC Emperor    schedule 11.01.2012


Ответы (3)


Звоните serverSocket.close(),

Я думаю, поскольку вы еще не выполняете ввод-вывод - вы не можете его прервать, а поскольку accept() не выдает InterruptedException, вы не сможете его прервать. Поток прерван, но этот флаг вы должны проверить сами Thread.isInterrupted().

См. Как я могу прервать метод accept() ServerSocket? .

person polve    schedule 11.01.2012
comment
Поскольку accept() нельзя прервать (что, на мой взгляд, немного странно, но пусть будет так), полагаю, мне придется использовать close()... Спасибо за помощь! - person MC Emperor; 11.01.2012

Ответ в вопросе. Вам нужно закрыть сокет. Это делается с помощью serverSocket.close(). Thread.interrupt() не заботятся о сокетах.

person JB Nizet    schedule 11.01.2012

Использовать это:

public class MyThread extends Thread {

    private boolean stop;
    private ServerSocket serverSocket;

    public MyThread(ServerSocket ss) {
        this.serverSocket = ss;
        this.stop = false;
    }

    public void setStop() {
        this.stop = true;
        if (this.ss != null) {
            this.ss.close();
        }
    }

    public void run() {
        while (!stop) {
            try {
                Socket socket = serverSocket.accept();
                // Create new thread to handle the incoming connection 
            }
            catch (IOException exc) { }
        }
    }
}

и из метода listen() просто вызовите метод setStop() потока.

person xyz    schedule 11.01.2012
comment
Нехорошо. Вы должны как минимум объявить stop как volatile, иначе компилятор может оптимизировать его таким образом, что разные потоки будут видеть разные значения. - person ivant; 13.08.2014