如何杀死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
,它会让你退出停顿的读取。