HttpClient4.5 http连接池示例

HttpClient 3.x,4.x都提供http连接池管理器,当使用了请求连接池管理器(比如PoolingHttpClientConnectionManager)后,HttpClient就可以同时执行多个线程的请求了。

hc3.x和4.x的早期版本,提供了PoolingClientConnectionManager,DefaultHttpClient等类来实现http连接池,但这些类在4.3.x版本之后大部分就已经过时,本文使用4.3.x提供的最新的PoolingHttpClientConnectionManager等类进行http连接池的实现.
废话不多说,下面是全部代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
public  class  PoolTest {
     private  static  void  config(HttpRequestBase httpRequestBase) {
         httpRequestBase.setHeader( "User-Agent" "Mozilla/5.0" );
         httpRequestBase.setHeader( "Accept" , "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" );
         httpRequestBase.setHeader( "Accept-Language" "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3" ); //"en-US,en;q=0.5");
         httpRequestBase.setHeader( "Accept-Charset" "ISO-8859-1,utf-8,gbk,gb2312;q=0.7,*;q=0.7" );
         
         // 配置请求的超时设置
         RequestConfig requestConfig = RequestConfig.custom()
                 .setConnectionRequestTimeout( 3000 )
                 .setConnectTimeout( 3000 )
                 .setSocketTimeout( 3000 )
                 .build();
         httpRequestBase.setConfig(requestConfig);        
     }
     public  static  void  main(String[] args) {
         ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
         LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory();
         Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                 .register( "http" , plainsf)
                 .register( "https" , sslsf)
                 .build();
         PoolingHttpClientConnectionManager cm =  new  PoolingHttpClientConnectionManager(registry);
         // 将最大连接数增加到200
         cm.setMaxTotal( 200 );
         // 将每个路由基础的连接增加到20
         cm.setDefaultMaxPerRoute( 20 );
         // 将目标主机的最大连接数增加到50
         HttpHost localhost =  new  HttpHost( "http://blog.csdn.net/gaolu" , 80 );
         cm.setMaxPerRoute( new  HttpRoute(localhost),  50 );
         
         //请求重试处理
         HttpRequestRetryHandler httpRequestRetryHandler =  new  HttpRequestRetryHandler() {
             public  boolean  retryRequest(IOException exception, int  executionCount, HttpContext context) {
                 if  (executionCount >=  5 ) { // 如果已经重试了5次,就放弃                    
                     return  false ;
                 }
                 if  (exception  instanceof  NoHttpResponseException) { // 如果服务器丢掉了连接,那么就重试                    
                     return  true ;
                 }
                 if  (exception  instanceof  SSLHandshakeException) { // 不要重试SSL握手异常                    
                     return  false ;
                 }                
                 if  (exception  instanceof  InterruptedIOException) { // 超时                    
                     return  false ;
                 }
                 if  (exception  instanceof  UnknownHostException) { // 目标服务器不可达                    
                     return  false ;
                 }
                 if  (exception  instanceof  ConnectTimeoutException) { // 连接被拒绝                    
                     return  false ;
                 }
                 if  (exception  instanceof  SSLException) { // ssl握手异常                    
                     return  false ;
                 }
                 
                 HttpClientContext clientContext = HttpClientContext.adapt(context);
                 HttpRequest request = clientContext.getRequest();
                 // 如果请求是幂等的,就再次尝试
                 if  (!(request  instanceof  HttpEntityEnclosingRequest)) {                    
                     return  true ;
                 }
                 return  false ;
             }
         };  
         
         CloseableHttpClient httpClient = HttpClients.custom()
                 .setConnectionManager(cm)
                 .setRetryHandler(httpRequestRetryHandler)
                 .build();
         // URL列表数组
         String[] urisToGet = {         
                 "http://blog.csdn.net/gaolu/article/details/48466059" ,
                 "http://blog.csdn.net/gaolu/article/details/48243103" ,
                 "http://blog.csdn.net/gaolu/article/details/47656987" ,
                 "http://blog.csdn.net/gaolu/article/details/47055029" ,
                 
                 "http://blog.csdn.net/gaolu/article/details/46400883" ,
                 "http://blog.csdn.net/gaolu/article/details/46359127" ,
                 "http://blog.csdn.net/gaolu/article/details/46224821" ,
                 "http://blog.csdn.net/gaolu/article/details/45305769" ,
                 
                 "http://blog.csdn.net/gaolu/article/details/43701763" ,
                 "http://blog.csdn.net/gaolu/article/details/43195449" ,
                 "http://blog.csdn.net/gaolu/article/details/42915521" ,
                 "http://blog.csdn.net/gaolu/article/details/41802319" ,
                 
                 "http://blog.csdn.net/gaolu/article/details/41045233" ,
                 "http://blog.csdn.net/gaolu/article/details/40395425" ,
                 "http://blog.csdn.net/gaolu/article/details/40047065" ,
                 "http://blog.csdn.net/gaolu/article/details/39891877" ,
                 
                 "http://blog.csdn.net/gaolu/article/details/39499073" ,
                 "http://blog.csdn.net/gaolu/article/details/39314327" ,
                 "http://blog.csdn.net/gaolu/article/details/38820809" ,
                 "http://blog.csdn.net/gaolu/article/details/38439375" ,
         };
         
         long  start = System.currentTimeMillis();        
         try  {
             int  pagecount = urisToGet.length;
             ExecutorService executors = Executors.newFixedThreadPool(pagecount);
             CountDownLatch countDownLatch =  new  CountDownLatch(pagecount);         
             for ( int  i =  0 ; i< pagecount;i++){
                 HttpGet httpget =  new  HttpGet(urisToGet[i]);
                 config(httpget);
                 //启动线程抓取
                 executors.execute( new  GetRunnable(httpClient,httpget,countDownLatch));
             }
             countDownLatch.await();
             executors.shutdown();
         catch  (InterruptedException e) {
             e.printStackTrace();
         finally  {
             System.out.println( "线程"  + Thread.currentThread().getName() +  ","  + System.currentTimeMillis() +  ", 所有线程已完成,开始进入下一步!" );
         }        
         
         long  end = System.currentTimeMillis();
         System.out.println( "consume -> "  + (end - start));
     }
     
     static  class  GetRunnable  implements  Runnable {
         private  CountDownLatch countDownLatch;
         private  final  CloseableHttpClient httpClient;
         private  final  HttpGet httpget;
         
         public  GetRunnable(CloseableHttpClient httpClient, HttpGet httpget, CountDownLatch countDownLatch){
             this .httpClient = httpClient;
             this .httpget = httpget;
             
             this .countDownLatch = countDownLatch;
         }
         @Override
         public  void  run() {
             CloseableHttpResponse response =  null ;
             try  {
                 response = httpClient.execute(httpget,HttpClientContext.create());
                 HttpEntity entity = response.getEntity();
                 System.out.println(EntityUtils.toString(entity,  "utf-8" )) ;
                 EntityUtils.consume(entity);
             catch  (IOException e) {
                 e.printStackTrace();
             finally  {
                 countDownLatch.countDown();
                 
                 try  {
                     if (response !=  null )
                         response.close();
                 catch  (IOException e) {
                     e.printStackTrace();
                 }
             }
         }
     }    
}

主要参考文档:
http://free0007.iteye.com/blog/2012308

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值