3

我真的很想知道如何中断被某些 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!
}
4

7 回答 7

3

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

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

于 2013-10-17T20:13:12.270 回答
3

在套接字上设置一个较短的读取超时并在您获取时循环,每次都SocketTimeoutException检查。Thread.isInterrupted()用于Thread.interrupt()中断线程。

于 2013-11-17T21:01:29.310 回答
2

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

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

从javadoc: -

关闭此套接字。当前在 accept() 中阻塞的任何线程都会抛出 SocketException。

于 2013-10-17T19:58:40.737 回答
1

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

于 2013-10-17T19:57:10.683 回答
1

注意没有InterruptedException声明被抛出:

public int read(byte[] b)
         throws IOException

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

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

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

于 2013-10-17T19:57:18.683 回答
1

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

但是如果你想关闭执行,而不是关闭流,你可以考虑利用FutureTask它提供取消的方式。

于 2013-10-17T20:11:56.900 回答
1

看看这篇博文,尤其是解决方案 4 – NIO with Buffering

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

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

根据javadocs:

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

但:

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

于 2013-10-17T20:28:52.757 回答