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

Din*_* Xu 67 java sockets multithreading

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

Ste*_*n C 57

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

  • 调用Socket.close()套接字上会关闭关联InputStreamOutputStream目的,并导致阻塞在插座或(相关联的)流操作的任何线程被解除阻塞.根据javadoc,socket上的操作本身就会抛出一个SocketException.

  • 调用Thread.interrupt()将(在某些情况下未指定)中断阻塞I/O操作,导致它抛出一个InterruptedIOException.

    请注意警告.显然,"interrupt()"方法不适用于"大多数"现代Java平台.(如果其他人有时间和倾向,他们可以调查这种方法的工作环境.但是,这种行为是特定于平台的事实应该足以说明,如果你只需要你的应用程序,你应该只使用它在特定的平台上工作.此时你可以轻松地为自己"尝试".)

  • 可能的第三种方法是打电话Socket.shutdownInput()和/或Socket.shutdownOutput().javadocs没有明确说明当前被阻止的读取和/或写入操作会发生什么,但认为它们将解除阻塞并抛出异常并不是不合理的.但是,如果javadoc没有说明会发生什么,那么应该假定该行为是特定于平台的.

  • 作为附录这一点,因为很多Java程序员这些天实际工作在Android上,应该注意的是,Android的一些版本在Socket.close(错误)时停止这项技术工作.但是,事先调用Socket.shutdownInput()确实有效. (7认同)
  • 请问,在什么情况下 thread.interrupt() 会中断阻塞 I/O 操作? (2认同)
  • Xu DXn - 没有记录.有些流实现了这一点,有些则没有实现.有关血淋淋的细节,请阅读OpenJDK源代码.我想说的是它可能会也可能不会起作用. (2认同)

rau*_*udi 16

我知道这个问题已经过时了,但似乎没有人能解开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;
}
Run Code Online (Sandbox Code Playgroud)

  • 仅当InputStream提供可以读取的数据时,此方法才有效.否则代码将被`in.read(...)`阻塞,并且检查线程是否被中断将永远不会被执行. (5认同)