HttpClient多线程并发

说明:以下的代码基于httpclient4.5.2实现。

我们要使用java的HttpClient实现get请求抓取网页是一件比较容易实现的工作:

要多线程执行get请求时上面的方法也堪用。不过这种多线程请求是基于在每次调用get方法时创建一个HttpClient实例实现的。每个HttpClient实例使用一次即被回收,也意味着每次调用这里的get方法都需要重新创建连接。这显然不是一种最优的实现。

HttpClient提供了多线程请求方案,可以查看官方文档的《Pooling connection manager》这一节。HttpCLient实现多线程请求是基于内置的连接池实现的,其中有一个关键的类即PoolingHttpClientConnectionManager,这个类负责管理HttpClient连接池。在PoolingHttpClientConnectionManager中提供了两个关键的方法:setMaxTotal和setDefaultMaxPerRoute。setMaxTotal设置连接池的最大连接数,setDefaultMaxPerRoute设置每个路由上的默认连接个数。此外还有一个方法setMaxPerRoute——单独为某个站点设置最大连接个数,像这样:

根据文档稍稍调整下我们的get请求实现:

这样就差不多了。不过对于我自己而言,我更喜欢httpclient的fluent实现,比如我们刚才实现的http get请求完全可以这样简单的实现:

我们要做的只是将以前的httpclient依赖替换为fluent-hc依赖:

并且这个fluent实现天然就是采用PoolingHttpClientConnectionManager完成的。它设置的maxTotal和defaultMaxPerRoute的值分别是200和100:

唯一一点让人不爽的就是Executor没有提供调整这两个值的方法。不过这也完全够用了,实在不行的话,还可以考虑重写Executor方法,然后直接使用Executor执行get请求:

就这样!

####

已有2条评论 发表评论

  1. bg2bkk /

    这里使用的是默认的HttpRequestRetryHandler,在一些连接超时、取conn超时等异常时不会默认重试,如果设置下这里就更妥帖了

    1. robin / 本文作者

      这里我觉得需要点个赞

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据