如何在不关闭某个套接字 IO 操作的情况下中断被该线程阻塞的线程



我真的很想知道如何中断被某些I/O操作阻塞的线程?I/O 是通过套接字进行的,我不想close()套接字。

我尝试使用Thread.interrupt()中断线程,但没有成功。

被 IO 操作阻止的线程:

void run(){
    byte[] data=new byte[1024];
    in.read(data);//blocked!
}

中断阻塞线程的线程(不起作用):

void run(){
    blockedThread.interrupt();//no success!
}

套接字和SocketTimeoutException循环上设置一个短暂的读取超时,每次都检查Thread.isInterrupted()。使用 Thread.interrupt() 中断线程。

如果你绝对不能/不想使用普通的java Socket类关闭套接字,你可以使用java.nio.SocketChannel来处理套接字。

SocketChannel实现了可中断通道,可以通过中断在套接字上等待 I/O 的线程来关闭该通道。在这种情况下,被阻止的读取将抛出 ClosedByInterruptException

您可以添加这样的方法,因为任何阻塞 IO 操作都会抛出 IOException:-

public void close() throws IOException {
    this.socket.close();
}

来自javadoc:-

关闭此套接字。当前在accept()中被阻止的任何线程都将 抛出套接字异常。

不幸的是,大多数平台上的 sun java impl 不会通过线程中断来处理 io 中断(我相信你可以通过一些 nio 的东西来解决这个问题,不确定)。 但是,我相信如果线程被阻止从套接字读取,并且您有该套接字的句柄,则可以从另一个线程异步关闭套接字(这将中断阻塞的线程)。

请注意,没有声明要抛出InterruptedException

public int read(byte[] b)
         throws IOException

从输入流中读取一定数量的字节,并将它们存储到缓冲数组 b 中。实际读取的字节数以整数形式返回。此方法将一直阻止,直到输入数据可用、检测到文件结尾或引发异常。

一些读取方法将通过Thread#interrupt()响应外部中断,要么关闭流,要么抛出异常。

否则,如果不以某种方式关闭或从另一个线程提供流,或者通过使用 Thread#stop() 终止线程,则无法停止此线程。最后一种方法只是最后的手段,不应出于各种原因使用。

看看这篇博文,尤其是解决方案 4 – 带有缓冲的 NIO

简而言之:对于常规文件,您必须使用 NIO ,使用扩展AbstractInterruptableChannelChannel,例如。 FileChannel .

使用套接字时,请使用Socket#close()中断/关闭。

根据javadocs:

此套接字上的 I/O 操作中当前阻塞的任何线程都将 抛出套接字异常。

但:

还有另一种解决方法:将异步IO与NIO一起使用,看看这里。异步 IO 的问题在于,处理起来非常复杂(与阻塞 IO 相比),因为您将不再在流上中继,而是在缓冲区上中继。

等待任何监视器的操作一样的I/O是不可中断的,这就是这些情况不需要InterruptedException芦丁的原因,但是根据Java 7 Documentation属于nio包的I/O类可以响应任何尝试入抛出流中断异常之一,其中之一是ClosedByInterruptionException,并且它的父类AsynchronousCloseException

但是,如果您想关闭执行头,而不是关闭流,您可以考虑使用提供取消方式的FutureTask

相关内容

  • 没有找到相关文章

最新更新