如何立即终止套接字IO操作上的线程阻塞?

2022-08-31 12:55:31

在Java的上下文中,我创建了一个新线程来在打开GUI窗口时读取网络输入,当我关闭窗口时,我想释放套接字资源并立即终止线程。现在我正在使用setSoTimeout方法,但我不想等待超时异常。任何人都可以给出一些建议吗?谢谢!


答案 1

有(可能)三种方法可以做到这一点:

  • 套接字上调用 Socket.close() 将关闭关联的和对象,并导致在 Socket 或(关联的)流操作中被阻止的任何线程被取消阻止。根据javadoc,套接字本身的操作将抛出一个SocketExceptionInputStreamOutputStream

  • 调用 Thread.interrupt() 将(在某些未指定的情况下)中断阻塞 I/O 操作,导致它引发中断的 IOException

    请注意注意事项。显然,“interrupt()”方法不适用于“大多数”现代Java平台。(如果其他人有时间和意愿,他们可以调查这种方法起作用的情况。但是,仅凭该行为是特定于平台的这一事实就足以说明,仅当您只需要应用程序在特定平台上工作时,才应使用它。在这一点上,您可以轻松地自己“尝试一下”。

  • 可能的第三种方法是调用 Socket.shutdownInput() 和/或 Socket.shutdownOutput()。javadocs没有明确说明当前被阻止的读取和/或写入操作会发生什么,但是认为它们将取消阻止并引发异常并不是没有道理的。但是,如果javadoc没有说明发生了什么,那么应该假设该行为是特定于平台的。


答案 2

我知道这个问题很老了,但由于似乎没有人解决“现代平台”的“谜团”,我做了一些研究。Thread.interrupt()

这在Windows7(64位)上的Java 8上进行了测试(但对于其他平台也可能如此)。

调用不会引发一个 发生的事情是该方法返回并设置了 -flag。Thread.interrupt()InterruptedIOExceptionInputStream.read()-1Thread.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;
}

推荐