【发布时间】:2012-02-29 14:49:54
【问题描述】:
感谢阅读。
这样一个烦人的问题发生在我身上,我值得有人帮助我。 我在java中使用httpcomponent(以前的httpclient的新版本)来打开一些url和scrap内容。并且使用multihtread来提高性能。
这就是问题所在:
1.threads共享一个HttpClient
1)定义
private static final ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager();
private static HttpHost proxy = new HttpHost("127.0.0.1",8086,"http");
private static DefaultHttpClient http = new DefaultHttpClient(cm);
2) 在我的初始功能中
cm.setMaxTotal(100);
http.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
3)然后是我的线程函数
public static String getUrl(String url, String Chareset)
{
HttpGet get = new HttpGet(url);//uri
get.setHeader("Content-Type", "text/html");
get.setHeader("User-Agent","Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.0; .NET CLR 1.1.4322; .NET CLR 2.0.50215;)");
get.setHeader("Accept-Charset", Chareset+";q=0.7,*;q=0.7");//"utf-8;q=0.7,*;q=0.7");
get.getParams().setParameter("http.socket.timeout",new Integer(CONNECTION_TIMEOUT));//20000
String result = "";
try {
HttpResponse response = http.execute(get);
if (response.getStatusLine().getStatusCode() != 200){//statusCode != HttpStatus.SC_OK) {
System.err.println("HttpGet Method failed: "
+ response.getStatusLine());//httpGet.getStatusLine()
}
HttpEntity entity = response.getEntity();
if (entity != null) {
result = EntityUtils.toString(entity);
EntityUtils.consume(entity);
entity = null;
}
} catch(java.net.SocketException ee)
{
ee.printStackTrace();
Logger.getLogger(DBManager.class.getName()).log(Level.SEVERE, null, ee);
}
catch (IOException e) {
//throw new Exception(e);
Logger.getLogger(DBManager.class.getName()).log(Level.SEVERE, null, e);//TODO Debug
} finally {
get.abort();//releaseConnection();//TODO http.getConnectionManager().shutdown();?
get = null;
}
return result;
}
4) 然后我创建了 10 个线程来调用 getUrl() 函数,但是在大约 1000 次循环之后,事情发生了:
**HttpGet Method failed: HTTP/1.0 503 Service Unavailable**
但是我用IE和代理打开了url,打开成功了。所以我的代理没有问题。
那怎么了?
2.然后我把httpclient的创建改成getUrl()函数,这样线程就不会共享HttpClient了,像这样:
public static String getUrl(String url, String Chareset)
{
HttpGet get = new HttpGet(url);//uri
get.setHeader("Content-Type", "text/html");
get.setHeader("User-Agent","Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.0; .NET CLR 1.1.4322; .NET CLR 2.0.50215;)");
get.setHeader("Accept-Charset", Chareset+";q=0.7,*;q=0.7");//"utf-8;q=0.7,*;q=0.7");
get.getParams().setParameter("http.socket.timeout",new Integer(CONNECTION_TIMEOUT));//20000
DefaultHttpClient http = new DefaultHttpClient(cm);//threads dont't share it
http.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
String result = "";
try {
HttpResponse response = http.execute(get);
if (response.getStatusLine().getStatusCode() != 200){//statusCode != HttpStatus.SC_OK) {
System.err.println("HttpGet Method failed: "
+ response.getStatusLine());//httpGet.getStatusLine()
}
HttpEntity entity = response.getEntity();
if (entity != null) {
result = EntityUtils.toString(entity);
EntityUtils.consume(entity);
entity = null;
}
} catch(java.net.SocketException ee)
{
ee.printStackTrace();
Logger.getLogger(DBManager.class.getName()).log(Level.SEVERE, null, ee);
}
catch (IOException e) {
//throw new Exception(e);
Logger.getLogger(DBManager.class.getName()).log(Level.SEVERE, null, e);//TODO Debug
} finally {
get.abort();//releaseConnection();//TODO http.getConnectionManager().shutdown();?
get = null;
http = null;//clean almost all the resources
}
return result;
}
然后在 10 个线程的大约 600 次循环之后,又发生了另一件事:
**Exception in thread "Thread-11" java.lang.OutOfMemoryError: Java heap space**
result = EntityUtils.toString(entity); 行发生异常
所以,真的需要一些帮助。
谢谢!
【问题讨论】:
-
原来是我被拒绝了。为了不被拒绝,我不得不使用第二种方式:在每个线程的每个循环中新建一个httpclient。还有Java gc()太慢了,所以我认为 sleep() 可能是个好主意,或者我可以用标志重置 prog 以指示进度。谢谢所有答案!
-
我终于想通了。这种方法有效。而其他地方有内存泄漏。对不起...
标签: java multithreading httpclient out-of-memory apache-httpcomponents