Как немедленно прекратить блокировку потока при работе с сокетом IO?

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

2 ответа

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

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

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

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

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

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

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

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

Таким образом, следующее можно считать "исправленным" методом read() 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;
}
Другие вопросы по тегам