java 原生的java httpclient pool能支持异步吗

HttpClient异步请求资源&(Java实现)
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。java 的Httpclient的使用 &同步与 异步方式
我主要讲最新的4.3.1的使用
从4.3版本开始开始 一些变化
那个ConnectionManager() 被遗弃 ,开始采用CloseableHttpClient 关闭
例如 我们前面版本 关闭 通过client.getConnectionManager().shutdown() 现在吗 只要client.close(); 当然这个client是上面的closeableHttpClient ,详细的见我下面的源代码
也许你会注意到apache 下面有个异步的支持httpclient 实际还有个ning-Asyn-http的项目,
我最近要做的事 是通过httpclient调用百度社会化登录的接口,由于 考虑到性能 个人觉得是异步方式在并发 多线程时候性能较好,为了验证这个问题 我在下面测试了下 花了2个小时的时间 写了2个工具类 ,get post方式 其中异步的方式采用的是 使用apache HttpAsynClient 4.3 编写的开源的lib库 unirest-java
详细介绍见 /p/unirest
&dependency&
&groupId&com.mashape.unirest&/groupId&
&artifactId&unirest-java&/artifactId&
&version&1.3.3&/version&
&/dependency&
下面 贴代码
首先是HttpUtil的代码
import org.apache.http.HttpE
import org.apache.http.HttpR
import org.apache.http.client.methods.HttpG
import org.apache.http.client.methods.HttpP
import org.apache.http.entity.StringE
import org.apache.http.impl.client.CloseableHttpC
import org.apache.http.impl.client.HttpClientB
import org.apache.http.util.EntityU
import com.alibaba.fastjson.JSON;
import java.io.IOE
import java.util.M
import java.util.concurrent.ExecutorS
import java.util.concurrent.E
import java.util.concurrent.S
* @author zhuyuping
* @version 1.0
* @created
上午10:43:54
* @function:使用同步阻塞库调用
异步非阻塞请见{@AsynHttpUtil}
public class HttpUtil {
* @param url
* @param params
* @return 这是post方式的同步方式
建议是用异步方式 {@AsynHttpUtil}
public static String Post(String url, Map params) {
CloseableHttpClient client =HttpClientBuilder.create().build();
String content =
HttpPost httppost = new HttpPost(url);
httppost.setHeader("accept", "application/json");
httppost.setEntity(new StringEntity(JSON.toJSONString(params)));
HttpResponse response = client.execute(httppost);
HttpEntity entity = response.getEntity();
content = EntityUtils.toString(entity);
EntityUtils.consume(entity);
} catch (Exception e){
} finally {
//client.getConnectionManager().shutdown();
client.close();
} catch (IOException e) {
e.printStackTrace();
* @param url
* @param params
* @return 这是get方式的同步方式
建议是用异步方式 {@AsynHttpUtil}
public static String get(String url, Map params) {
CloseableHttpClient client =HttpClientBuilder.create().build();
String content =
HttpGet get = new HttpGet(url + "?" + stringify(params));
HttpResponse response = client.execute(get);
HttpEntity entity = response.getEntity();
content = EntityUtils.toString(entity);
EntityUtils.consume(entity);
} catch (Exception e){
} finally {
//client.getConnectionManager().shutdown();
client.close();
} catch (IOException e) {
e.printStackTrace();
public static String get(String url) {
CloseableHttpClient client =HttpClientBuilder.create().build();
//new DefaultHttpClient();
String content =
HttpGet get = new HttpGet(url);
HttpResponse response = client.execute(get);
HttpEntity entity = response.getEntity();
content = EntityUtils.toString(entity);
EntityUtils.consume(entity);
} catch (Exception e){
} finally {
// client.getConnectionManager().shutdown(); //4.3 被遗弃掉了
client.close();
} catch (IOException e) {
e.printStackTrace();
public static String stringify(Map&String, Object& map){
if (map == null)
StringBuilder builder = new StringBuilder();
for (Map.Entry&String, Object& entry : map.entrySet()){
builder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
return builder.deleteCharAt(builder.length() - 1).toString();
public static void main(String[] args) {
int thread_num = 50;
int client_num = 2000;
final String tokenUrl = "/social/oauth/2.0/token";
ExecutorService exec = Executors.newCachedThreadPool();
// 50个线程可以同时访问
final Semaphore semp = new Semaphore( thread_num );
// 模拟460个客户端访问
long ftime=System.currentTimeMillis();
for( int index = 0 ; index & client_ index ++ )
final int NO =
Runnable run = new Runnable()
public void run()
// 获取许可
semp.acquire();
//System.out.println( "Thread:" + NO );
String json=HttpUtil.get(tokenUrl);
//System.out.println("json is "+json);
Thread.sleep( 2000 );
semp.release();
catch ( Exception e )
e.printStackTrace();
exec.execute( run );
// 退出线程池
long etime=System.currentTimeMillis();
System.out.println("httpUtil同步方式执行50个并发访问 2000个客服端所花费的时间 "+(etime-ftime)+" s");
exec.shutdown();
AsynHttpclient的代码
import com.mashape.unirest.http.HttpR
import com.mashape.unirest.http.JsonN
import com.mashape.unirest.http.U
import com.mashape.unirest.http.async.C
import com.mashape.unirest.request.GetR
import com.mashape.unirest.request.HttpRequestWithB
import java.util.M
import java.util.concurrent.ExecutorS
import java.util.concurrent.E
import java.util.concurrent.F
import java.util.concurrent.S
import org.json.JSONO
* @author zhuyuping
* @version 1.0
* @created
上午10:42:55
* @function:使用异步库 async HttpClient调用
public class AsynHttpUtil {
* @param url
* @param params
* @return 这是异步的post方法 记住 最后要把Unirest.shutdown(); 队列 关闭掉
public static org.json.JSONObject post(String url,Map&String,Object& params){
//boolean flag=
//int size=0;
//while(flag){
HttpRequestWithBody request=Unirest.post(url).header("accept", "application/json");
if(params!=null){
request.fields(params);
Future&HttpResponse&JsonNode&& future = request.asJsonAsync();
org.json.JSONObject ojson=future.get().getBody().getObject();
} catch (Exception e) {
/*finally{
Unirest.shutdown();
} catch (IOException e) {
e.printStackTrace();
if(resp.getCode()==200){
org.json.JSONObject ojson=resp.getBody().getObject();
Unirest.shutdown();
} catch (IOException e1) {
e1.printStackTrace();
if(size&4)
Unirest.shutdown();
} catch (IOException e1) {
e1.printStackTrace();
//这是异步回调函数 执行惊醒处理
/*Future&HttpResponse&JsonNode&& future = request.asJsonAsync(new Callback&JsonNode&() {
public void failed(UnirestException e) {
System.out.println("The request has failed");
public void completed(HttpResponse&JsonNode& response) {
int code = response.getCode();
// Map&String, String& headers = response.getHeaders();
JsonNode body = response.getBody();
InputStream rawBody = response.getRawBody();
public void cancelled() {
System.out.println("The request has been cancelled");
* @param url
* @param params
* @return 这是异步的post方法 记住 最后要把Unirest.shutdown(); 队列 关闭掉
public static org.json.JSONObject get(String url,Map&String,Object& params){
GetRequest request=
if(params==null)
request=Unirest.get(url);
request=Unirest.get(url+"?" + stringify(params));
Future&HttpResponse&JsonNode&& future = request.asJsonAsync();
HttpResponse&JsonNode& resp =
resp = future.get();
org.json.JSONObject ojson=resp.getBody().getObject();
} catch (Exception e) {
public static String stringify(Map&String, Object& map){
if (map == null)
StringBuilder builder = new StringBuilder();
for (Map.Entry&String, Object& entry : map.entrySet()){
builder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
return builder.deleteCharAt(builder.length() - 1).toString();
public static void main( String [] args ) throws Exception
int thread_num = 50;
int client_num = 2000;
final String tokenUrl = "/social/oauth/2.0/token";
ExecutorService exec = Executors.newCachedThreadPool();
// 50个线程可以同时访问
final Semaphore semp = new Semaphore( thread_num );
// 模拟460个客户端访问
long ftime=System.currentTimeMillis();
for( int index = 0 ; index & client_ index ++ )
final int NO =
Runnable run = new Runnable()
public void run()
// 获取许可
semp.acquire();
//System.out.println( "Thread:" + NO );
JSONObject json=AsynHttpUtil.get(tokenUrl, null);
//System.out.println("json is "+json);
Thread.sleep( 2000 );
semp.release();
catch ( Exception e )
e.printStackTrace();
exec.execute( run );
// 退出线程池
long etime=System.currentTimeMillis();
System.out.println("AsynhttpUtil同步方式执行50个并发访问 2000个客服端所花费的时间 "+(etime-ftime)+" s");
Unirest.shutdown();
exec.shutdown();
当让 由于可能框架不一样 编写的作者能力不一样
所以结果并不能由太大的可比性
大家要用到的话 可以复制过去参考
下面是运行的结果
HttpUtil的同步阻塞方式
结果是异步方式性能 在上面条件下优于 同步方式 当让我测试了 一些其他 比如把上面2个值调小一些 有可能 很相近差不多
人气:1957
Copyright (C) , All Rights Reserved.
版权所有 闽ICP备号
processed in 0.056 (s). 13 q(s)java-httpclient-18k 改进一,支持http异步,回调,https - CSDN博客
java-httpclient-18k 改进一,支持http异步,回调,https
这篇文章是上篇文章的继续 “”,化了几天业余时间,大概实现了http 以下功能
1、异步调用和回调
2、多个http的并行调用
3、https(同步异步都支持)
github地址:
使用示例:
本文已收录于以下专栏:
相关文章推荐
Http和https网络请求
    主要总结一下使用到的网络请求框架,一种是同步网络请求org.apache.httpcomponents的httpclient,另一种是异步网络请求com.ning...
安卓学习部分就暂时不更新了,因为现在工作中直接做安卓开发了,以后会陆续记录工作中遇到的问题。
言归正传,最近工作开发安卓应用,由于我对安卓还不太熟,就先负责和服务端网络通信。要求:异步、回调。
httpClient 4.5版本升级后@Deprecated方法升级,java发送https请求,
httpClient连接池同时支持http和https的发送。
根据上一篇文章,接下来来封装http连接网络的代码,仅供参考
     Http封装的get与post方法
package com.qq.wx.voice.
import java.i...
* 书本:《Thinking In Java》
* 功能:关于java中的闭包与回调,这里回调区别于C++,C++中回调的话寄托于指针
* 文件:Callbacks.java
* 时间:201...
java, 异步, 消息
用线程池,回调,进行图片的异步加载,实现图片的缓存,并且以渐隐动画的方式显示出来
不必多说,线程池,回调,这些在java里面都算是非常重要的角色。
线程池:线程池就是管理多线程的一个东西,在多线程...
对回调很简单的理解就是a对象调用b对象方法,b对象开始执行,执行完以后,b对象又调用a对象方法,这就是回调。
本文出自xiaanming的博客(http://blog.c...
他的最新文章
讲师:宋宝华
讲师:何宇健
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)博客分类:
使用Netty 构造一个异步的httpclient
这篇文档目的是通过一个 Netty构造的Http客户端demo,来说名如何使用 Netty。
2 Httpclient 使用方法,详见代码HttpClient.java中main函数。
HttpClient
HttpClient
ChannelPipeline line
HttpResponseHandler
第一步构造HttpClient实例hc ,hc是可以反复使用的,可以多线程 多个请求的并发使用。
第二步使用HttpCleint的get方法访问sohu首页。HttpCleint支持Http的GET PUT HEAD......方法。与其对应的是函数成员函数get put head......。
第三步get方法(其他方法如 put post...也一样) 会返回一个ChannelPipeline ,line维护着一个或者多个handler 用于异步的处理I/O数据,如HttpResponseHandler是一个处理get访问返回数据的handler。这里向line里添加了一个handler 也可以添加多个。
此段代码不会阻塞,都是立即返回。
3 代码详情
下边吧程序展开成顺序执行的代码 来说明。
a 主要流程
//以下代码在
HttpClient.java HttpClient()中
bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()
bootstrap.setPipelineFactory(new HttpClientPipelineFactory());
ClientBootstrap 是Netty中的助手类。帮助建立Netty程序,维护主要的Netty类。如bootstrap 包括一个
ChannelFactory,一个PipelineFactory,
Channel,Pipeline的作用和使用方法后边介绍。然后程序进行如下:
//以下代码在
HttpClient.java retrieve()中
ChannelFuture future = bootstrap.connect(new InetSocketAddress(“host”, port));
future.addListener(new ConnectOk(request));
bootstrap.connect方法是打开一个channel,这里可以看出channel是一个类似链接,事实上channel确实是Netty抽象出来的“链接”,统一了tcp udp
Nio Oio等网络接口的访问方式。 而这个channel 是由ChannelFactory产生的,
NioClientSocketChannelFactory
打开的Channel使用了java的Nio 异步接口。所以coonect方法并没有返回一个Channel 而是一个 ChannelFuture。 ChannelFutre提供添加一个addListener的方法,使得这个channel真正被打开的时候
调用用户设置的回调。这里使用自定一个的一个类ConnectOk
(实现了ChannelFutureListener接口)。当channel被真正打开的时候,会调用ConnectOk
的operationComplete方法。operationComplete方法里才可以往channel里写入请求。
在写入之前 还得做些工作。如下:
//以下代码在
HttpClient.java retrieve()中,略有区别
ChannelPipeline line
= future.getChannel().getPipeline();
HttpResponseHandler
这些代码的目的就是设置 等到网络应答,也就是获得http响应后应做哪些工作。ClientBootstrap 会为每个channel生成一个ChannelPipeline。ChannelPipeline的作用就是处理channel上的数据。至于如何处理就要看ChannelPipeline上有哪些ChannelHandler,下边详述 先看ChannelPipeline是如何产生的。
ClientBootstrap 中包含了一个HttpClientPipelineFactory 这是一个实现了ChannelPipelineFactory接口的getPipeline方法的类。 在getPipeline方法中可以按照自己需求定义生成一个PipeLine。
//以下代码在
HttpClientPipelineFactory.java getPipeline()中
ChannelPipeline pipeline = pipeline();
pipeline.addLast("decoder", new HttpResponseDecoder());
pipeline.addLast("aggregator", new HttpChunkAggregator(1048576));
pipeline.addLast("encoder", new HttpRequestEncoder());
这里根据自己定义生成一个pipeline。 pipeline()是Netty提供的生成pipeline的静态函数。因为要做的是http访问所以在getPipeline中配置了 Netty提供的访问http的几个ChannelHandler。分别是把http响应数据解码成HttpResponse对象的HttpResponseDecoder,合并chunk数据的HttpChunkAggregator,把HttpRequest对象编码成http请求协议的HttpRequestEncoder。
ChannelPipeline不仅设置了处理channel的handler 而且设置了处理顺序 ,这个可以参考文档。大体顺序是从channel流入的数据一步步被解析生成为程序的对象,流出的时候是把程序中的对象一步步解析生成通讯协议。
在设置好这些后。可以往channel里边写入数据了。
//以下代码在
HttpClient.java ConnectOk类中
operationComplete
Channel channel = future.getChannel();
channel.write(request);
上边说到当channel真正被打开后会调用ConnectOk的operationComplete方法。在这里可以获得这个准备好的channel 然后调用write方法。这可以看到往channel里边写入了一个 HttpRequest对象。这个HttpRequest对象会被pipeline 编码成http请求最终发给服务器。注意write放法也是异步的,它会马上返回一个
ChannelFuture 对象。如果想要在write完成后做点什么 可以给这个ChannelFuture对象添加一个Listener 等待回调。
等得到http应答后 pipeline会把channel中的数据一步步解析成HttpResponse对象,里边包括了 header cookie request ....一切信息。后边就是提供一个自己定义的handler 来处理这个response
代码的基本流程就是这样。
浏览 15372
兄弟你的get,post方法上为什么返回ChannelPipline呢,不应该是返回CannelFuture吗?如果按照你这样的连接都关闭了,你根本就没有办法在客户端显示响应结果了啊,关闭连接也应该是在结果返回给客户端再关闭吧?兄弟,你还是没理解异步的作用啊。。。你的想法还停留在同步。
fengshihao
浏览: 39403 次
来自: 北京
&div class=&quote_title ...
兄弟你的get,post方法上为什么返回ChannelPipl ...
翻译的不错
跟原文对照看
有收获 呵呵
我也觉得这样分开,js重绘页面比较好,而且如果做控件的话,看起 ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'

我要回帖

更多关于 java httpclient get 的文章

 

随机推荐