Как немедленно прекратить блокировку потока при работе с сокетом IO? - PullRequest
65 голосов
/ 13 декабря 2010

В контексте Java я создаю новый поток для чтения сетевого ввода при открытии окна с графическим интерфейсом, а когда я закрываю окно, я хочу освободить ресурс сокета и немедленно прекратить поток. Теперь я использую метод setSoTimeout, но я не хочу ждать исключения тайм-аута. Кто-нибудь может дать какое-нибудь предложение? Спасибо!

Ответы [ 2 ]

55 голосов
/ 13 декабря 2010

Есть (потенциально) три способа сделать это:

  • Вызов Socket.close() на сокете закроет связанные объекты InputStream и OutputStream и вызовет разблокировку любых потоков, заблокированных в операциях Socket или (связанных) потоков. Согласно Javadoc, операции над самим сокетом приведут к SocketException.

  • Вызов Thread.interrupt() будет (при некоторых обстоятельствах, которые не указаны) прервать операцию блокирующего ввода-вывода, заставив ее сгенерировать InterruptedIOException.

    Обратите внимание на предостережение. Очевидно, подход «interrupt ()» не работает на «большинстве» современных платформ Java. (Если бы у кого-то было время и желание, он мог бы исследовать обстоятельства, в которых работает этот подход. Однако одного лишь факта, что поведение зависит от платформы, должно быть достаточно, чтобы сказать, что вы должны использовать его только в том случае, если вам нужно только ваше приложение работать на конкретной платформе. В этот момент вы можете легко "попробовать" это для себя.)

  • Возможный третий способ сделать это - позвонить Socket.shutdownInput() и / или Socket.shutdownOutput(). Javadocs не говорят явно, что происходит с операциями чтения и / или записи, которые в настоящее время заблокированы, но вполне разумно думать, что они разблокируют и сгенерируют исключение. Однако, если Javadoc не говорит, что происходит, то следует предположить, что его поведение зависит от платформы.

15 голосов
/ 18 апреля 2016

Я знаю, что этот вопрос старый, но, похоже, никто не решил «тайну» Thread.interrupt() на «современных платформах», я провел некоторое исследование.

Это проверено на Java 8 на Windows7 (64-bit) (но, возможно, это будет верно и для других платформ).

Вызов Thread.interrupt() делает не бросает InterruptedIOException Что происходит, когда метод InputStream.read() возвращаетс -1 и Thread.interrupted() -флагом установлено.

Таким образом, следующее «исправленное» чтение () может быть выброшено InterruptedIOException:

static final int read(Socket socket, byte[] inData) 
    throws SocketTimeoutException, // if setSoTimeout() was set and read timed out
           InterruptedIOException, // if thread interrupted
           IOException             // other erors
{
    InputStream in = socket.getInputStream();

    int readBytes = in.read( inData, 0, inData.length);

    if  ( Thread.interrupted() )
    {
        throw new InterruptedIOException( "Thread interrupted during socket read");
    }

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