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

时间:2013-10-17 19:53:23

标签: java multithreading sockets io stream

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

7 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:3)

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

答案 2 :(得分:2)

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

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

来自javadoc: -

  

关闭此套接字。任何目前在accept()中被阻止的线程都会   抛出一个SocketException。

答案 3 :(得分:1)

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

答案 4 :(得分:1)

注意声明没有声明InterruptedException被抛出:

  

public int read(byte[] b)
         throws IOException
     

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

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

你不能否则停止这个线程而不以某种方式关闭或从另一个线程中提供流,或者用Thread#stop()杀死该线程。最后一种方法只是最后的手段,不应该出于各种原因使用。

答案 5 :(得分:1)

等待任何监视器的操作的I / O不可中断,这是因为这些情况不需要InterruptedException rutine,而是根据Java 7 Documentation I / O类属于nio程序包的任何内容都可以响应任何尝试进行中断,抛出其中一个流中断异常,其中一个是ClosedByInterruptionException,它是父类AsynchronousCloseException

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

答案 6 :(得分:1)

查看this blog post,尤其是解决方案4 - 带缓冲的NIO

简而言之:对于常规文件,您必须使用NIO,请使用扩展Channel的{​​{1}},例如。 AbstractInterruptableChannel

使用套接字时,请使用FileChannel来中断/关闭。

根据javadocs:

  

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

<强> BUT:

还有另一种解决方法:使用Socket#close()使用异步IO,查看here。 异步IO的问题是,它处理起来非常复杂(与阻塞IO相比),因为你不再继续在流上进行中继,而是缓冲。