170314、工具:apache httpClient多线程并发情况下安全实用及工具类分享
简单用法介绍:介绍来源网络
建立连接:在HttpClient中使用多线程的一个主要原因是可以一次执行多个方法。在执行期间,每一个方法都使用一个HttpConnection实例。由于在同一时间多个连接只能安全地用于单一线程和方法和有限的资源,我们就必须确保连接分配给正确的方法。而MultiThreadedHttpConnectionManager完全可以代替我们完成这一项工作,这样我们就不必去考虑多线程带来安全的问题。
MultiThreadedHttpConnectionManager connectionManager =new MultiThreadedHttpConnectionManager();
HttpClient client = new HttpClient(connectionManager);
以上代码中的HttpClient就在多线程中执行多个方法了。当我们再次调用httpClient.executeMethod()方法时,就会去Connection Manager中去请求HttpConneciton的实例,这样就避免了线程安全问题,因为HttpClient已经帮我们做了。
释放连接:Connection Management比较重要的是当连接不再使用时,一定要手动释放。这样做的原因是HttpClient不能够确定哪个方法不被使用,哪个方法还在使用。这是因为Response body不是由HttpClient来自动读取其数据的,而是由使用HttpClient的应用程序来完成的。当读取Response的数据是时,必须使用此方法的连接。这样,在Response的数据在读取前,HttpClient是没有释放连接的。所有这就要求在读取完Response的数据后,应用程序及时的使用releaseConnection()方法来释放连接。特别注意,无论执行的方法或是否也不例外被抛出。对于每一个HttpClient.executeMethod方法必须有一个method.releaseConnection ( )来释放连接。
重用HttpClient实例:一般说来,建议一个通讯组件,甚至说一个应用软件就始终维持一个HttpClient对象实例存在。但是如果你的应用很稀罕才用到它,而且还不允许这么一个实例一直存在,那么,这里强烈建议,一定要显式地shut down 它的MultiThreadedHttpConnectionManager 。这样做是确保连接池里的Connection得到释放。
HttpMethod并发执行:如果应用程序逻辑允许并发执行多个HTTP请求,(例如对多个服务器的多个并发请求,或对同一个服务器代表不同用户身份的多个请求) ,应用程序可以为每一个HTTP session开启一个专门的线程,这样的设计自然将带来显著的性能提升。 而当使用一个线程安全的连接管理器MultiThreadedHttpConnectionManager 时,HttpClient能保证线程安全。这样,多个线程可以共享这么一个线程安全的HttpClient实例。请注意,应用程序的每个各自执行的线程必须使用各自的HttpMethod实例;并且可配置各自的HttpState实例和/或HostConfiguration实例(代表一个特定的会话状态和主机配置)。这个共享的HttpClient和其标配的MultiThreadedHttpConnectionManager将为各线程带来最高的性能。
使用流来发送和接收数据:HttpClient同时支持Stream和String/byte[]两种方式来发送和接受数据,但是由于String/byte[]的方式会造成内存中有一份数据的拷贝或缓存,那么当请求或应答报文比较大,或者在高并发的应用中,使用String/byte[]就会造成额外的内存开销,所以使用流的方式来传输数据是更好的选择。
HttpClient的三种超时说明
/* 从连接池中取连接的超时时间 */
ConnManagerParams.setTimeout(params, 1000);
/* 连接超时 */
HttpConnectionParams.setConnectionTimeout(params, 2000);
/* 请求超时 */
HttpConnectionParams.setSoTimeout(params, 4000);
第一行设置ConnectionPoolTimeout:这定义了从ConnectionManager管理的连接池中取出连接的超时时间,此处设置为1秒。
第二行设置ConnectionTimeout: 这定义了通过网络与服务器建立连接的超时时间。Httpclient包中通过一个异步线程去创建与服务器的socket连接,这就是该socket连接的超时时间,此处设置为2秒。
第三行设置SocketTimeout: 这定义了Socket读数据的超时时间,即从服务器获取响应数据需要等待的时间,此处设置为4秒。
以上3种超时分别会抛出ConnectionPoolTimeoutException,ConnectionTimeoutException与SocketTimeoutException。
工具类:jar包commons-httpclient-3.1.jar
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.protocol.Protocol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
public class HttpClientTemplate {
private static Logger logger = LoggerFactory.getLogger(HttpClientTemplate.class);
private MultiThreadedHttpConnectionManager multiThreadConnManager;
private HttpClient client;
public HttpClientTemplate() {
HttpConnectionManagerParams params = new HttpConnectionManagerParams();
params.setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler());
params.setMaxTotalConnections(10);
params.setDefaultMaxConnectionsPerHost(5);
params.setSoTimeout(10 * 1000);
params.setConnectionTimeout(10 * 1000);
multiThreadConnManager = new MultiThreadedHttpConnectionManager();
multiThreadConnManager.setParams(params);
}
private HttpClient getHttpClient() {
if (client == null)
synchronized (this) {
client = new HttpClient(multiThreadConnManager);
HttpClientParams params = new HttpClientParams();
params.setContentCharset("UTF-8");
client.setParams(params);
}
return client;
}
//生成get方法
private GetMethod genMethod(String baseUrl, String queryString) {
GetMethod get = new GetMethod(baseUrl);
get.setQueryString(queryString);
return get;
}
//生成get方法
private GetMethod genMethod(String baseUrl, Map<String, Object> paramMap) {
GetMethod get = new GetMethod(baseUrl);
HttpMethodParams params = new HttpMethodParams();
params.setContentCharset("UTF-8");
get.setParams(params);
if (paramMap != null) {
NameValuePair[] nvp = new NameValuePair[paramMap.values().size()];
int i = 0;
for (Map.Entry<String, Object> entry: paramMap.entrySet()) {
nvp[i++] = new NameValuePair(entry.getKey(), entry.getValue()
.toString());
}
get.setQueryString(nvp);
}
return get;
}
public String execute(String baseUrl, Map<String, Object> paramMap) {
if(logger.isDebugEnabled()) {
logger.debug("[sending] url={}, param={}", baseUrl, JSON.toJSONString(paramMap));
}
try {
GetMethod method = genMethod(baseUrl, paramMap);
String result = execute(method);
if(logger.isDebugEnabled()) {
logger.debug("[receiving] result ={}, url={}, param={}",result, baseUrl, JSON.toJSONString(paramMap));
}
return result;
}
catch(Exception e) {
logger.error("[http exception] url={}, param={}", baseUrl, JSON.toJSONString(paramMap), e);
return null;
}
}
//json格式请求
public String excuteJson(String baseUrl, Map<String, Object> paramMap)
throws HttpException, IOException
{
if(logger.isDebugEnabled()) {
logger.debug("[sending json] url={}, param={}", baseUrl, JSON.toJSONString(paramMap));
}
JSONObject json = new JSONObject();
json.putAll(paramMap);
PostMethod method = new PostMethod(baseUrl);
RequestEntity requestEntity = new StringRequestEntity(json.toString(), "application/json", "UTF-8");
method.setRequestEntity(requestEntity);
String result = execute(method);
if(logger.isDebugEnabled()) {
logger.debug("[receiving json] result ={}, url={}, param={}",result, baseUrl, JSON.toJSONString(paramMap));
}
return result;
}
//post请求
public String executePost(String baseUrl, Map<String, Object> paramMap){
try {
if(logger.isDebugEnabled()) {
logger.debug("[sending post] url={}, param={}", baseUrl, JSON.toJSONString(paramMap));
}
PostMethod method = new PostMethod(baseUrl);
HttpMethodParams params = new HttpMethodParams();
params.setContentCharset("UTF-8");
method.setParams(params);
if (paramMap != null) {
NameValuePair[] nvp = new NameValuePair[paramMap.values().size()];
int i = 0;
for (Map.Entry<String, Object> entry: paramMap.entrySet()) {
nvp[i++] = new NameValuePair(entry.getKey(), entry.getValue()
.toString());
}
method.addParameters(nvp);
}
String result = execute(method);
if(logger.isDebugEnabled()) {
logger.debug("[receiving post] result ={}, url={}, param={}",result, baseUrl, JSON.toJSONString(paramMap));
}
return result;
}
catch(Exception e) {
logger.error("[http post exception] url={}, param={}", baseUrl, JSON.toJSONString(paramMap), e);
return null;
}
}
public String executePost(String baseUrl, Map<String, Object> paramMap,
Map<String, Object> headerParams) throws HttpException, IOException {
if(logger.isDebugEnabled()) {
logger.debug("[sending head] url={}, param={}, head={}", baseUrl,
JSON.toJSONString(paramMap), JSON.toJSONString(headerParams));
}
PostMethod method = new PostMethod(baseUrl);
HttpMethodParams params = new HttpMethodParams();
params.setContentCharset("UTF-8");
method.setParams(params);
if (paramMap != null) {
NameValuePair[] nvp = new NameValuePair[paramMap.values().size()];
int i = 0;
for (Map.Entry<String, Object> entry: paramMap.entrySet()) {
nvp[i++] = new NameValuePair(entry.getKey(), entry.getValue()
.toString());
}
method.addParameters(nvp);
}
if (headerParams != null) {
// HttpMethodParams mparams = new HttpMethodParams();
// mparams.setContentCharset("UTF-8");
// mparams.setVirtualHost(headerParams.get("hostUrl").toString());
// method.setParams(mparams);
method.getParams().setVirtualHost(
headerParams.get("hostUrl").toString());
}
String result = execute(method, headerParams);
if(logger.isDebugEnabled()) {
logger.debug("[receiving head] result ={}, url={}, param={}, head={}",result, baseUrl,
JSON.toJSONString(paramMap), JSON.toJSONString(headerParams));
}
return result;
}
public String execute(String url) throws HttpException, IOException {
GetMethod method = new GetMethod(url);
return execute(method);
}
public String execute(String baseUrl, String queryString)
throws HttpException, IOException {
GetMethod method = genMethod(baseUrl, queryString);
return execute(method);
}
private String execute(HttpMethod method) throws HttpException, IOException {
try {
int statusCode = getHttpClient().executeMethod(method);
if (200 != statusCode) {
throw new HttpException("status code: " + statusCode);
} else {
// return method.getResponseBodyAsString();
InputStream resStream = method.getResponseBodyAsStream();
BufferedReader br = new BufferedReader(new InputStreamReader(
resStream, "UTF-8"));
StringBuffer resBuffer = new StringBuffer();
String resTemp = "";
while ((resTemp = br.readLine()) != null) {
resBuffer.append(resTemp);
}
return resBuffer.toString();
}
} finally {
if (null != method)
method.releaseConnection();
}
}
private String execute(HttpMethod method, Map<String, Object> headerParams)
throws HttpException, IOException {
try {
HttpClient httpClient = getHttpClient();
if (headerParams != null) {
HostConfiguration hf = new HostConfiguration();
if (headerParams.get("hostUrl") != null) {
hf.setHost(headerParams.get("hostUrl").toString(), 80,
Protocol.getProtocol("http"));
}
httpClient.setHostConfiguration(hf);
}
int statusCode = httpClient.executeMethod(method);
if (200 != statusCode) {
throw new HttpException("status code: " + statusCode);
} else {
// return method.getResponseBodyAsString();
InputStream resStream = method.getResponseBodyAsStream();
BufferedReader br = new BufferedReader(new InputStreamReader(
resStream, "UTF-8"));
StringBuffer resBuffer = new StringBuffer();
String resTemp = "";
while ((resTemp = br.readLine()) != null) {
resBuffer.append(resTemp);
}
return resBuffer.toString();
}
} finally {
if (null != method)
method.releaseConnection();
}
}
public static class Factory {
private static HttpClientTemplate instance = new HttpClientTemplate();
public static HttpClientTemplate getClient() {
return Factory.instance;
}
}
public static void main(String[] args) {
HttpClientTemplate clientTemplate = HttpClientTemplate.Factory.instance;
Map<String, Object> paramMap = new LinkedHashMap<>();
String result = clientTemplate.executePost("", paramMap);
}
}
170314、工具:apache httpClient多线程并发情况下安全实用及工具类分享的更多相关文章
- 喜提JDK的BUG一枚!多线程的情况下请谨慎使用这个类的stream遍历。
你好呀,我是歪歪. 前段时间在 RocketMQ 的 ISSUE 里面冲浪的时候,看到一个 pr,虽说是在 RocketMQ 的地盘上发现的,但是这个玩意吧,其实和 RocketMQ 没有任何关系. ...
- 多线程并发情况下 重复insert问题
代码逻辑: if(数据不存在){ insert(); } 线程启动后,发现数据库表中有相同的记录 解决方案 synchronized同步代码块即加同步锁,synchronized同步代码块的功能: 当 ...
- PHP通过加锁实现并发情况下抢码实现
需求:抢码功能 要求: 1.特定时间段才开放抢码: 2.每个时间段放开的码是有限的: 3.每个码不允许重复: 实现: 1.在不考虑并发的情况下实现: function get_code($len){ ...
- PHP通过加锁实现并发情况下抢码功能
本文基于php语言使用加锁实现并发情况下抢码功能,特定时间段开放抢码并不允许开放的码重复: 需求:抢码功能 要求: 1.特定时间段才开放抢码: 2.每个时间段放开的码是有限的: 3.每个码不允许重复: ...
- Jackson高并发情况下,产生阻塞
情况:在高并发情况下,查看线程栈信息,有大量的线程BLOCKED. 从线程栈得知,线程栈中出现了阻塞,锁在了com.fasterxml.jackson.databind.ser.SerializerC ...
- Linux的虚拟内存管理-如何分配和释放内存,以提高服务器在高并发情况下的性能,从而降低了系统的负载
Linux的虚拟内存管理有几个关键概念: Linux 虚拟地址空间如何分布?malloc和free是如何分配和释放内存?如何查看堆内内存的碎片情况?既然堆内内存brk和sbrk不能直接释放,为什么不全 ...
- c# redis 利用锁(StackExchange.Redis LockTake)来保证数据在高并发情况下的正确性
之前有写过一篇介绍c#操作redis的文章 http://www.cnblogs.com/axel10/p/8459434.html ,这篇文章中的案例使用了StringIncrement来实现了高并 ...
- 面试官问:HashMap在并发情况下为什么造成死循环?一脸懵
这个问题是在面试时常问的几个问题,一般在问这个问题之前会问Hashmap和HashTable的区别?面试者一般会回答:hashtable是线程安全的,hashmap是线程不安全的. 那么面试官就会紧接 ...
- 关于WCF服务在高并发情况下报目标积极拒绝的异常处理
最近弄了个wcf的监控服务,偶尔监控到目标服务会报一个目标积极拒绝的错误.一开始以为服务停止了,上服务器检查目标服务好好的活着.于是开始查原因. 一般来说目标积极拒绝(TCP 10061)的异常主要是 ...
随机推荐
- C复杂声明举例
首先,一些国外的研究成果: 一个用英语解析复杂声明的网站:http://cdecl.org 图表说明复杂声明(英):http://c-faq.com/decl/spiral.anderson.html ...
- atitit.为什么 java开发要比php开发速度慢??
atitit.为什么 java开发要比php开发速度慢?? 1. 界面开发方面vs php 1 2. 架构繁琐 1 3. 环境配置复杂 1 4. 类库jar包冲突(严重) 1 5. 配置文件热部署的缺 ...
- filebeat+kafka失败
filebeat端配置 #----------------------------- Kafka output -------------------------------- output.kafk ...
- You-Get 视频下载工具 Python命令行下载工具
You-Get 是一个命令行工具, 用来下载各大视频网站的视频, 是我目前知道的命令行下载工具中最好的一个, 之前使用过 youtube-dl, 但是 youtube-dl 吧, 下载好的视频是分段的 ...
- Python 元祖的操作
注意:元祖定义后不可修改,单个元祖后面必须加逗号,否则认为是字符串:tuple = ('apple',) 1.定义元祖 tuple = ('apple','banana','grape','orang ...
- FreeRTOS 调度锁,任务锁和中断锁
以下转载自安富莱电子: http://forum.armfly.com/forum.php 调度锁调度锁就是 RTOS 提供的调度器开关函数,如果某个任务调用了调度锁开关函数,处于调度锁开和调度锁关之 ...
- FreeRtos——移植
现在准备的简单程序LED灯的工程目录中增加freertos文件夹: 在 source目录下的portable目录下只留下下面的文件夹: 为什么呢? 把对应文件移植在工程中之后,添加头文件路径如下图: ...
- springMVC介绍
http://www.iteye.com/blogs/subjects/springMVC —————————————————————————————————————————————————————— ...
- 多个 label checkbox 组合 显示在同一个水平线上[前提Bootstrap框架]
<th align="left" valign="middle"> <label class="checkbox inline fo ...
- 打印-print.js
//打印开始// strPrintName 打印任务名// printDatagrid 要打印的datagridfunction CreateFormPage(ctx,strPrintName, pr ...