如何终止 BufferedInputStream .read() 调用
Posted
技术标签:
【中文标题】如何终止 BufferedInputStream .read() 调用【英文标题】:How to kill a BufferedInputStream .read() call 【发布时间】:2012-02-20 22:13:27 【问题描述】:我正在编写一个程序来从服务器下载非常大的文件 (~2GB)。我已经编写了能够恢复部分完成下载的程序,
为了模拟糟糕的互联网连接,我在下载过程中一直将以太网线从路由器中拔出。不幸的是,这导致我的程序挂起以下调用:
while((bytesRead = in.read(data)) > 0)
(其中 bytesRead 是一个 int,in 是从 HttpURLConnection 构建的 BufferedInputStream,data 是一个字节数组)。
我试图通过在另一个线程上调用 in.close() 来“中断”调用,但在互联网连接恢复之前它没有效果(此时抛出异常)。
有什么方法可以防止互联网连接中断冻结我的程序?
【问题讨论】:
有类似回答的问题:***.com/questions/804951/… 【参考方案1】:我发现唯一可靠的方法是将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 示例,但我知道你可以自定义套接字初始化。
【讨论】:
你有这方面的例子吗?我一直在寻找很长一段时间,我一直无法找到任何有用的东西。本质上,我需要的是一种可靠、可中断、可恢复的方式来下载非常大的文件(~2gb)。我找不到任何等效于 HttpURLConnection.setRequestProperty()... @Samusaaron3。我添加了一个如何创建 interraptible 套接字的示例。【参考方案2】:有关处理这种情况的代码,请参阅http://thushw.blogspot.com/2010/10/java-urlconnection-provides-no-fail.html
已编辑:实际上,使用setSoTimeout
(如 Joop Eggen 的链接评论中所建议)设置套接字超时(以毫秒为单位)可能更好。
【讨论】:
我试过从一个单独的线程调用 .disconnect() ,但是即使在调用之后,也没有抛出 IOException,所以我仍然卡住了...... @DNA 要使用 setSoTimeout,您应该有一个 Socket,但 HttpURLConnection 不允许您检索其底层 Socket。 (我假设 OP 需要依赖 HttpURLConnection)【参考方案3】:您的URLConnection
上有.setReadTimeout(int timeout)
吗?
-- 编辑
查看@DNA 的答案以获得简洁的解决方案:
简而言之,您可以生成一个.disconnect()
s URLConnection
的并行线程(在让您的第二个线程休眠 timeout 毫秒之后),从而触发一个 IOException
,它会得到你摆脱了停滞不前的阅读。
【讨论】:
这是一个很好的做法,但如果服务器返回一些数据并且 then 卡住,它就无济于事 - 它只适用于服务器根本没有返回数据的情况.以上是关于如何终止 BufferedInputStream .read() 调用的主要内容,如果未能解决你的问题,请参考以下文章
BufferedInputStream 到 byte[] 以通过 Socket 发送到数据库
Java IO BufferedInputStream 和 BufferedOutputStream