HttpClient4.x多线程环境下共享HttpClient实例


在实际应用中,网络爬虫(网络蜘蛛)往往需要每分钟爬取上百个网页甚至更多,这样的要求,单线程的爬虫(蜘蛛/spider)实在难以完成,势必要引入多线程技术。而在多线程环境下,为了避免浪费资源,需要重用HttpClient实例,由此带来了资源争抢和同步的问题。

在HttpClient3的时候,我们可以使用池化技术来自行实现一个HttpClient池,满足这样的需要,但是在HttpClient4中,相关的解决方案已经内置其中,于是我们不必大费周章地实现一个对象池,来手动管理HttpClient实例,这样我们有更多的时间和精力来专注页面内容的处理。

接下来,我们将演示如何使用ThreadSafeClientConnManager实现在多线程环境中使用同一个HttpClient对象,已达到节约资源的目的。

package cn.ysh.studio.crawler.httpclient;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;import org.apache.http.protocol.BasicHttpContext;import org.apache.http.protocol.HttpContext;import org.apache.http.util.EntityUtils;/**
 * 在多线程环境中使用同一个HttpClient对象
 * 
 * @author Shenghany
 * @date 2013-5-19
 */publicclassClientMultiThreadedExecution{publicstaticvoid main(String[] args)throwsException{// 创建一个使用ThreadSafeClientConnManager连接管理器的HttpClient实例// 当这个HttpClient实例被超过1个线程使用时,必须使用ThreadSafeClientConnManagerThreadSafeClientConnManager tscm =newThreadSafeClientConnManager();HttpClient httpclient =newDefaultHttpClient(tscm);try{// 创建一个需要请求的URL数组String[] urisToGet ={"http://www.yshjava.cn","http://hc.apache.org/","http://hc.apache.org/httpcomponents-client-ga/","http://svn.apache.org/viewvc/httpcomponents/"};// 为每一个URL创建一个请求线程GetThread[] threads =newGetThread[urisToGet.length];for(int i =0; i < threads.length; i++){HttpGet httpget =newHttpGet(urisToGet[i]);
                threads[i]=newGetThread(httpclient, httpget, i +1);}// 启动所有请求线程for(int j =0; j < threads.length; j++){
                threads[j].start();}// join所有请求线程for(int j =0; j < threads.length; j++){
                threads[j].join();}}finally{// 当不再需要HttpClient实例时,关闭连接管理器以确保释放所有占用的系统资源
            httpclient.getConnectionManager().shutdown();}}/**
     * 执行Get请求的线程
     */staticclassGetThreadextendsThread{privatefinalHttpClient httpClient;privatefinalHttpContext context;privatefinalHttpGet httpget;privatefinalint id;publicGetThread(HttpClient httpClient,HttpGet httpget,int id){this.httpClient = httpClient;this.context =newBasicHttpContext();this.httpget = httpget;this.id = id;}/**
         * 执行Get请求并打印一些状态信息
         */@Overridepublicvoid run(){System.out.println(id +" - about to get something from "+ httpget.getURI());try{// 执行Get请求HttpResponse response = httpClient.execute(httpget, context);System.out.println(id +" - get executed");// 获得以字节数组接收响应实体内容HttpEntity entity = response.getEntity();if(entity !=null){byte[] bytes =EntityUtils.toByteArray(entity);System.out.println(id +" - "+ bytes.length +" bytes read");}}catch(Exception e){
                httpget.abort();System.out.println(id +" - error: "+ e);}}}}

 注:可以考虑工作队列 工作线程


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM