如何杀死BufferedInputStream .read()调用

我正在编写一个程序来从服务器下载非常大的文件(~2GB)。 我编写了程序以便能够恢复部分完成的下载,

为了模拟一个糟糕的互联网连接,我一直在下载中途时将我的以太网线从我的路由器中拉出来。 不幸的是,这导致我的程序挂起以下调用: while((bytesRead = in.read(data)) > 0)

(其中bytesRead是int,in是从HttpURLConnection构建的BufferedInputStream,数据是字节数组)。

我试图通过在另一个线程上调用in.close()来“中断”调用,但是在恢复互联网连接之前它没有任何效果(此时会抛出exception)。

有什么方法可以阻止被切断的互联网连接冻结我的程序吗?

我找到的唯一可靠的方法是将Socket实例化为InterruptibleChannel ,并在卡住的IO线程上执行中断。 (顺便说一下,你不必使用InterruptibleChannels的异步NIO调用,阻塞I / O工作正常,你只是有一个非常好的和统一的方式来踢卡住的交换)

虽然看起来像URLConnection不允许你连接自定义Socket工厂。

也许你应该从Apache调查HttpClient 。

编辑

以下是创建可中断套接字的方法。

 import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; import java.nio.channels.SocketChannel; final SocketAddress remoteAddr = new InetSocketAddress( serverAddress, servicePort ); final SocketChannel socketChannel = SocketChannel.open( ); socketChannel.connect( remoteAddr ); // Here java.io.Socket is obtained Socket socket = socketChannel.socket( ); 

我没有HttpClient示例,但我知道您可以自定义套接字初始化。

有关处理此情况的代码,请参见http://thushw.blogspot.com/2010/10/java-urlconnection-provides-no-fail.html

编辑 :实际上,使用setSoTimeout设置套接字超时(以毫秒为单位)(如Joop Eggen的链接注释中所示)可能更好。

您的URLConnection上有.setReadTimeout(int timeout)吗?

– 编辑

请参阅@DNA的答案以获得一个简洁的解决方案:

简而言之,你可以产生一个并行线程.disconnect()URLConnection (让你的第二个线程在超时毫秒内hibernate),从而触发一个IOException ,它会让你退出停顿的读取。