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


73

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


11
我不明白为什么会得到-1?!?我认为问题很明确,而且当场。
Max Kielland 2010年

Answers:


60

有(可能)三种方法可以执行此操作:

  • 调用Socket.close()套接字将关闭关联的InputStreamOutputStream对象,并使在Socket或(关联的)流操作中阻塞的所有线程都被解除阻塞。根据javadoc,对套接字本身的操作将抛出SocketException

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

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

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


2
请在什么情况下thread.interrupt()会中断阻塞的I / O操作?
Dingxin Xu 2010年

3
Xu DXn-未记录。有些流实现了此功能,而另一些则没有。有关详细信息,请阅读OpenJDK源代码。我要说明的是,它可能会或可能不会起作用。
斯蒂芬·C

1
可以肯定,大多数jvm实现支持可中断的io操作。我认为也许sun solaris jvm在某一点上支持了它。
jtahlborn

8
作为对此的补充,由于如今许多Java程序员实际上都在Android上工作,因此应注意,某些版本的Android在Socket.close()中存在一个错误,该错误使该技术无法正常工作。但是,事先调用Socket.shutdownInput()确实可以。
Jules 2012年

您能否澄清现有的阻塞操作是否将引发SocketException,还是仅套接字上的新操作将引发SocketException?
user239558 2013年

18

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

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

调用Thread.interrupt()不会引发InterruptedIOException 什么情况是,该InputStream.read()方法返回与-1Thread.interrupted()-flag设置。

因此,可以将以下内容视为“更正”的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;
}

1
这个答案值得更多投票,因为Java在输入/输出流操作期间被中断时的行为并不是人们所期望的。
Tom N.

8
仅当InputStream提供可以读取的数据时,此方法才有效。否则,代码将被阻塞,in.read(...)并且将永远不会执行检查线程是否被中断的检查。
罗伯特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.