Уничтожение потока в Java с помощью Thread.interrupt - PullRequest
0 голосов
/ 03 ноября 2011

У меня в приложении чата Swing запущен поток, который бесконечно прослушивает сокет для дейтаграмм.Когда я закрываю это приложение, я выполняю следующий код:

listenThread.interrupt();
socket.close();

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

Ответы [ 4 ]

4 голосов
/ 03 ноября 2011

interrupt() нельзя использовать для прерывания операции ввода-вывода, такой как чтение или запись в сокет.Чтобы прервать ввод / вывод, закрытие сокета является правильным способом.После того, как ваш поток получает IOException, он должен проверить, не прервался ли он за это время, и затем корректно завершиться.

Пример кода в вашем потоке ввода / вывода:

while( !Thread.currentThread().isInterrupted() ) {
  try {
    doRead();
  } catch ( IOException ioe ) {
    // Log exception or whatever
  }
}
1 голос
/ 03 ноября 2011

interrupt() только уведомляет ветку о намерении кого-то остановить его.Это до нитки, чтобы правильно выйти.Если поток ожидает на мониторе, он получит InterruptedException, в противном случае вы можете проверить isInterrupted() в текущем потоке.Однако, если он ожидает ввода-вывода, вам может не повезти, и ваш единственный выбор - дождаться истечения времени ожидания сокета.Затем вы проверите, прерывается ли поток, и закроете сокет.

0 голосов
/ 04 ноября 2011

Я предполагаю, что вы реализовали этот простой способ и сделали:

 DatagramSocket s = new DatagramSocket( port );
 DatagramPacket p = new DatagramPacket( new byte[256], 256);
 s.receive( p );

Теперь, глядя на Javadoc, нет способа заставить DatagramSocket.receive() выдать исключение InterruptedException. Закрытие сокета - единственный способ заставить его перестать слушать.

Лучшей реализацией этого было бы установить тайм-аут для DatagramSocket, используя DatagramSocket.setSoTimeout( int ), равный чему-то небольшому, например, 2 секунды, а затем проверить, не прерывался ли ваш сервер. Таким образом, вы получите что-то подобное для своего серверного кода (не обрабатывает исключения):

DatagramSocket s = new DatagramSocket( port );
s.setSoTimeout( 2000 ); // 2 second time out

while( running ){ // boolean running flag, check for interrupt here
    try{
        DatagramPacket p = new DatagramPacket( new byte[256], 256);
        s.receive( p );
        //do stuff
    } catch ( SocketTimeoutException e ){
        //timed out
    }
}//end while
0 голосов
/ 04 ноября 2011

Если выдается исключение, перехватите его и выйдите из потока чтения UDP.Ожидается исключение, когда сокет закрыт от другого потока - используйте его!

Если это не так, установите флаг прерывания и верните UDP-чтение (), отправив ему дейтаграмму в локальном стеке TCP.из сокета в потоке, запрашивающем отключение.UDP - это служба сообщений без установления соединения, и он очень рад получить дейтаграмму из другого потока в том же ящике.Дейтаграмма может содержать инструкцию завершения работы или вы можете проверять флаг isInterrupted после каждого возврата read (), на случай, если он установлен.

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