How to terminate a thread blocking on socket IO operation instantly?

In the context of Java, I create a new thread to read network input when open a GUI window, and when i close the window, i want to release the socket resource and terminate the thread immediately. Now i am using setSoTimeout method, but i don't want to wait the timeout exception. Could anybody give some suggestion? Thanks!

33493 次浏览

有(潜在的)三种方法可以做到这一点:

  • Calling Socket.close() on the socket will close the associated InputStream and OutputStream objects, and cause any threads blocked in Socket or (associated) stream operations to be unblocked. According to the javadoc, operations on the socket itself will throw a SocketException.

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

    Note the caveat. Apparently the "interrupt()" approach doesn't work on "most" modern Java platforms. (If someone else had the time and inclination, they could possible investigate the circumstances in which this approach works. However, the mere fact that the behavior is platform specific should be sufficient to say that you should only use it if you only need your application to work on a specific platform. At which point you can easily "try it" for yourself.)

  • A possible third way to do this is to call Socket.shutdownInput() and/or Socket.shutdownOutput(). The javadocs don't say explicitly what happens with read and/or write operations that are currently blocked, but it is not unreasonable to think that they will unblock and throw an exception. However, if the javadoc doesn't say what happens then the behavior should be assumed to be platform specific.

我知道这个问题已经很老了,但是似乎没有人能够在“现代平台”上解决 Thread.interrupt()的“奥秘”,所以我做了一些研究。

这在 Windows7的 Java8上进行了测试(64位)(但对于其他平台也可能是这样)。

调用 Thread.interrupt()没有抛出 InterruptedIOException 发生的情况是,InputStream.read()方法返回 -1,并且设置了 Thread.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;
}