高分求解如何避免这种IO阻塞(附代码和DEBUG的截图)

Aniao 2008-04-19 04:24:02
多线程的Spider程序,每个线程负责下载一个网页并且把内容转化成BYTE数组,问题来了,这些线程之间没有任何的同步关系,完全是互不相干的,也不共享数据,但是通过DEBUG发现,有些线程无法结束,大部分被卡在了BufferedInputStream.read()方法,还有少量被卡在了HttpURLConnection.getInputStream()方法,尤其是后者我不能理解,我设置了超时时间的,应该不会一直卡在那里啊.下面是我的多线程类Record的大概代码.
public class Record implements Runnable
{
private byte[] content;
private String url;
public Record(String URL)
{
this.url = URL;
}
public void run()
{
Download();
}
public byte[[ Donwload()
{
URL Url;
HttpURLConnection http;
java.io.InputStream urlstream=null;
try
{
Url = new URL(url);
http = (HttpURLConnection) Url.openConnection();
http.setRequestProperty("User-Agent", "IE/6.0");
http.setConnectTimeout(1);
http.connect();
urlstream = http.getInputStream();
} catch (Exception e)
{
System.out.println("下载页面失败:" + url + e.getClass() + e.getMessage()
+ e.getStackTrace());
return;
}

if (urlstream==null)
{
return;
}
content= InputStreamToByte(urlstream);
}
synchronized public byte[] InputStreamToByte(InputStream iStrm)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BufferedInputStream bis = new BufferedInputStream(iStrm);
int b = 0;
try
{
while ((b = bis.read()) != -1)
baos.write(b);
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return baos.toByteArray();
}
}



现在附上两种被阻塞状态的DEBUG截图






我个人的思路是准备换成非阻塞的方式来取得数据,但是nio包里没有包装比较好的通过HTTP协议下载页面的类啊,用SocketChannel自己写的话对于一个SPIDER来说,还要处理https一类的东西,很是麻烦啊.
...全文
155 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
J_Factory 2008-04-20
  • 打赏
  • 举报
回复
学习
kokobox 2008-04-20
  • 打赏
  • 举报
回复
http.setConnectTimeout(1); -----------lz设置的超时时间太少了,1毫秒,很容易抛socket异常。

建议lz设置成为http.setConnectTimeout(10000);

注意流的关闭,发现lz都不关闭流的,一定要关闭流,很占资源的,流也很容易引起阻塞。


hmsuccess 2008-04-20
  • 打赏
  • 举报
回复
http.setConnectTimeout(1); -----------lz设置的超时时间太少了,1毫秒,很容易抛socket异常。
guanshenglang 2008-04-20
  • 打赏
  • 举报
回复
我顶

*****************************************************************************
欢迎使用CSDN论坛专用阅读器 : CSDN Reader(附全部源代码)

http://www.cnblogs.com/feiyun0112/archive/2006/09/20/509783.html
guanshenglang 2008-04-20
  • 打赏
  • 举报
回复
dg

*****************************************************************************
欢迎使用CSDN论坛专用阅读器 : CSDN Reader(附全部源代码)

http://www.cnblogs.com/feiyun0112/archive/2006/09/20/509783.html
dracularking 2008-04-20
  • 打赏
  • 举报
回复
如ls 看getInputStream介绍
Returns an input stream that reads from this open connection. A SocketTimeoutException can be thrown when reading from the returned input stream if the read timeout expires before data is available for read.
如果在输入流可读之前就超时的话抛SocketTimeoutException了

Aniao 2008-04-19
  • 打赏
  • 举报
回复
恩,非常感谢楼上的
云上飞翔 2008-04-19
  • 打赏
  • 举报
回复
答:
1)http.setConnectTimeout(1);这个仅是设置连接的超时不是网络等待读的超时。另外注意:单位是毫秒
2)http.setReadTimeout(毫秒);这个才是网络等待读的超时。时间一到还有读到数据,则抛出java.net.SocketTimeoutException异常。

以上仅供你参考
Aniao 2008-04-19
  • 打赏
  • 举报
回复
我就是想知道下载网页的异步IO怎么写,查了很多都是关于服务器通信的,都只涉及服务器地址和端口,根本没有对应资源地址
  • 打赏
  • 举报
回复
那就设置好超时时间
不过最好还是使用异步IO

62,623

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧