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

5lhxktic  于 2022-12-21  发布在  Java
关注(0)|答案(2)|浏览(201)

在Java环境下,我创建了一个新的线程,在打开GUI窗口时读取网络输入,当我关闭窗口时,我想释放套接字资源并立即终止线程。现在我使用setSoTimeout方法,但我不想等待超时异常。谁能给予我一些建议?谢谢!

v1l68za4

v1l68za41#

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

  • 在套接字上调用Socket.close()将关闭关联的InputStreamOutputStream对象,并导致任何在套接字中阻塞的线程或(关联的)流操作被解除阻塞。根据javadoc,在套接字本身上的操作将抛出SocketException
  • 调用Thread.interrupt()将(在某些未指定的情况下)中断阻塞I/O操作,导致其抛出InterruptedIOException

注意警告。显然“打断()”方法在“大多数”现代Java平台上不起作用。(如果其他人有时间和意愿,他们可能会调查这种方法起作用的环境。然而,行为是特定于平台的这一事实本身就足以说明,只有当您只需要应用程序在特定平台上工作时才应该使用它。这时你可以很容易地自己“尝试一下”。)

  • 第三种可能的方法是调用Socket.shutdownInput()和/或Socket.shutdownOutput(). javadoc没有明确说明当前被阻塞的读和/或写操作会发生什么,但认为它们会解除阻塞并抛出异常也是合理的.然而,当javadoc没有说明发生了什么时,行为应该被假定为特定于平台.
qaxu7uf2

qaxu7uf22#

我知道这个问题已经很老了,但由于似乎没有人解决“现代平台”上Thread.interrupt()的“谜团”,我做了一些研究。
这在Windows7(64位)上的Java 8上进行了测试(但在其他平台上也可能如此)。
调用Thread.interrupt()不会抛出InterruptedIOException。发生的情况是InputStream.read()方法返回-1,并且设置了Thread.interrupted()标志。
因此,以下内容可视为抛出InterruptedIOException的“更正”read():

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;
}

相关问题