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