В контексте Java я создаю новый поток для чтения сетевого ввода, когда открываю окно GUI, и когда я закрываю окно, я хочу освободить ресурс сокета и немедленно прекратить поток. Теперь я использую метод setSoTimeout, но я не хочу ждать исключения тайм-аута. Может ли кто-нибудь дать какое-нибудь предложение? Спасибо!
Как немедленно завершить блокировку потока при операции ввода-вывода сокета?
Ответ 1
Есть (потенциально) три способа сделать это:
-
Вызов
Socket.close()
в сокете закроет связанные объектыInputStream
иOutputStream
и вызовет блокирование любых потоков в Socket или (связанных) потоковых операциях, которые должны быть разблокированы. Согласно javadoc, операции с самим сокером будут вызыватьSocketException
. -
Вызов
Thread.interrupt()
будет (при некоторых обстоятельствах, которые не указаны) прервать операцию блокирующего ввода-вывода, бросьтеInterruptedIOException
.Обратите внимание на оговорку. По-видимому, подход "interrupt()" не работает на "большинстве" современных платформ Java. (Если у кого-то еще было время и склонность, они могли бы расследовать обстоятельства, в которых работает этот подход. Однако сам факт, что поведение является специфичным для платформы, должен быть достаточным, чтобы сказать, что вы должны использовать его только в том случае, если вам нужна ваша заявка для работы на определенной платформе. В этот момент вы можете легко "попробовать" для себя.)
-
Возможный третий способ сделать это - вызвать
Socket.shutdownInput()
и/илиSocket.shutdownOutput()
. В javadocs явно не указано, что происходит с операциями чтения и/или записи, которые в настоящее время заблокированы, но небезосновательно думать, что они разблокируют и выдают исключение. Однако, если javadoc не говорит, что происходит, тогда поведение следует считать специфичным для платформы.
Ответ 2
Я знаю, что этот вопрос старый, но, как кажется, никто не решил "тайну" Thread.interrupt()
на "современных платформах", я сделал некоторые исследования.
Это проверено на Java 8 на Windows7 (64-разрядная версия) (но это, вероятно, будет верно и для других платформ).
Вызов Thread.interrupt()
делает не бросок InterruptedIOException
Случается, что метод InputStream.read()
возвращается с параметрами -1
и Thread.interrupted()
-flag.
Таким образом, можно считать "исправленное" чтение() throw 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;
}