前几天碰到了一个问题
项目开发中碰到的一个线程问题(一),当时说的不太清楚
,这里好好总结下。
现象:多线程Http请求,在服务端发现总会有相同参数的请求。当时认为是HttpClient在多线程下是线程非安全的,
wangzhangxing 提到:
引用
PoolingClientConnectionManager cm = new PoolingClientConnectionManager();
cm.setMaxTotal(100);
然后new DefaultHttpClient(cm));
这样出来的client就是线程安全的了
。
事实上代码里也确实是这么做的:
/**
* 初始化HttpClient对象
*
* @return HttpClient对象
*/
private HttpClient getHttpClient()
{
HttpClient httpClient = null;
try
{
// ThreadSafeClientConnManager\PoolingClientConnectionManager
PoolingClientConnectionManager pccm = new PoolingClientConnectionManager(getSchemeRegistry());
// pccm.setDefaultMaxPerRoute(20);
httpClient = new DefaultHttpClient(pccm, prepareHttpParams());
}
catch (Exception e)
{
e.printStackTrace();
httpClient = new DefaultHttpClient();
}
return httpClient;
}
自己又认真狠看了几遍代码,其中的调用顺序是这样的,DataServiceImpl 是具体的业务实现类,通过HttpHelper对象获取服务端的信息。
package org.okura.timer;
/**
* 服务接口实现类
*
* @author okura
* @since 2012-10-10
*/
public class DataServiceImpl implements IDataService
{
private HttpHelper httpHelper;
public DataServiceImpl()
{
httpHelper = new HttpHelper();
}
@Override
public void getProduct(String type, String date)
{
// System.out.println(Thread.currentThread().getName() +
// "---DataServiceImpl---type:" + type +",date:" + date);
httpHelper.requestString(HttpUrlUtil.getProductUrl(type, date));
// System.out.println("type:" + type +",date:" + date + "--" + response);
}
}
HttpHelper代码,其中有些方法省略,详细代码可以下载附件查看
public class HttpHelper
{
/** Http请求方法对象 */
private HttpRequestBase request;
/**
* 发送Http请求,返回文本形式的请求响应
*
* @param url url地址
* @return
*/
public String requestString(String url)
{
try
{
HttpResponse stringResponse = send(url);
// 判断请求是否成功
if (!isResponseSuccessStatus(stringResponse))
{
return null;
}
System.out.println(Thread.currentThread().getName() + "---url:" + url);
return parseHttpResponse2String(stringResponse);
}
catch (Exception e)
{
e.printStackTrace();
System.out.println("requestString()" + url);
return null;
}
}
/**
* 发送Http请求,返回请求响应
*
* @param url url地址
* @return
*/
private HttpResponse send(String url) throws Exception
{
try
{
// 初始化Http请求方法和参数
initGet(url);
// 进行Http请求
return doRequest();
}
catch (Exception e)
{
e.printStackTrace();
throw new Exception("http send request exception");
}
}
/**
* Get方法
*
* @param url
*/
private void initGet(String url)
{
request = new HttpGet(url);
}
/**
* 初始化HttpClient对象
*
* @return HttpClient对象
*/
private HttpClient getHttpClient()
{
HttpClient httpClient = null;
try
{
//ThreadSafeClientConnManager\PoolingClientConnectionManager
httpClient = new DefaultHttpClient(new PoolingClientConnectionManager(getSchemeRegistry()),
prepareHttpParams());
}
catch (Exception e)
{
e.printStackTrace();
httpClient = new DefaultHttpClient();
}
return httpClient;
}
/**
* 进行Http请求,得到Http响应
*
* @return Http响应
* @throws Exception
*/
private HttpResponse doRequest() throws Exception
{
HttpClient httpClient = getHttpClient();
// setProxy(httpClient);// 设置代理
return httpClient.execute(request);
}
}
从上面代码可以看到,HttpHelper对象是DataServiceImpl 的全局变量,虽然HttpHelperHttpClient是通过PoolingClientConnectionManager 获取HttpClient的,没有进行同步操作,在多线程就很可能会出现获取出来的对象是相同的,(个人理解),这里抛砖引玉,哪位牛人帮详解下,^_^。
那接下来怎么修改呢,很简单,只修改HttpHelper中的HttpClient变量使用范围:
public class HttpHelper
{
/** HttpClient对象 */
private HttpClient httpClient;
/**
* 构造函数
*/
public HttpHelper()
{
httpClient = getHttpClient();
}
/**
* 发送Http请求,返回文本形式的请求响应
*
* @param url url地址
* @return
*/
public String requestString(String url)
{
HttpGet request = null;
try
{
// 初始化Http请求方法和参数
request = new HttpGet(url);
// 进行Http请求
HttpResponse stringResponse = httpClient.execute(request);
// 判断请求是否成功
if (!isResponseSuccessStatus(stringResponse))
{
return null;
}
System.out.println(Thread.currentThread().getName() + "---url:" + url);
return parseHttpResponse2String(stringResponse);
}
catch (Exception e)
{
request.abort();
httpClient.getConnectionManager().shutdown();
e.printStackTrace();
System.out.println("requestString()" + url);
return null;
}
}
/**
* 初始化HttpClient对象
*
* @return HttpClient对象
*/
private HttpClient getHttpClient()
{
try
{
// ThreadSafeClientConnManager\PoolingClientConnectionManager
PoolingClientConnectionManager pccm = new PoolingClientConnectionManager(getSchemeRegistry());
// pccm.setDefaultMaxPerRoute(20);
httpClient = new DefaultHttpClient(pccm, prepareHttpParams());
}
catch (Exception e)
{
e.printStackTrace();
httpClient = new DefaultHttpClient();
}
return httpClient;
}
}
有几点自己以后要注意:
1、要注意代码细节,多测试才能发现问题。
2、程序引用的代码即使不能钻研的很明白,至少能理解使用的具体场合。
3、最重要的一点,以后要恶补基础啦, 三天不学习,不知道南北极哪,
分享到:
相关推荐
基本情况 在一个项目开发过程中,遇到了小票自动打印的业务需求,原本计划使用NodeJS构建打印服务,调用本地电脑打印机进行数据打印,最后可参考资料偏少,由于项目紧急且对NodeJS的熟悉程度目前也还不够,所以转而...
java开发工作两年遇到的技术问题以及查找到的解决方案还有一些积累,涉及前端技术,android开发,java后台以及数据库sql优化,session共享,单点登录,kafka入门,websocket,线程安全等。
在开发中,大家讲学习到基本的组件,适配UI,数据的存储,多线程下载,开机广播,闹钟提醒,短信发送等实际项目开发中碰到的有用的知识点。通过课程学习,让大家能够掌握Android软件开发的流程,注意点,及优化。...
无论您是运行还是二次开发,部署过程若遇到问题,请及时私信交流,欢迎学习。 基于QT和C++开发的仿win10的任务管理器项目源码+项目说明(操作系统课设).zip 功能模块 ![功能模块](img/module.png) * 仿照Windows10...
本资源是一个非常详细和实用的 Java 项目总结报告,涵盖了项目管理、Java 语言、数据库设计、需求分析、表单设计、数据校验、分页和批量删除、团队合作、问题解决等方面的内容,对于 Java 项目开发和软件工程有很大...
Tomcat 是一个开源的 Web 服务器软件,广泛应用于 Java Web 开发中。在 Linux 系统下,Tomcat 可以轻松地安装和配置,以便发布 Web 项目。 Linux 系统的特点 Linux 是一个免费、开源的操作系统,具有多线程、多...
《Visual C 开发实例大全(提高卷)》以开发人员在项目开发中经常遇到的问题和必须掌握的技术为核心,介绍了应用Visual C 进行程序开发各个方面的知识和技巧,主要包括Windows操作、鼠标和键盘相关、注册表、线程和...
《Visual C 开发实例大全(提高卷)》以开发人员在项目开发中经常遇到的问题和必须掌握的技术为核心,介绍了应用Visual C 进行程序开发各个方面的知识和技巧,主要包括Windows操作、鼠标和键盘相关、注册表、线程和...
《Android项目高手过招FAQ》是一本专为Android开发者打造的实用指南,旨在解决他们在开发过程中遇到的各种常见问题。本书汇集了大量实战经验和技巧,以Q&A的形式呈现,方便读者快速查找和解决问题。 本书涵盖了...
例如,在一个项目中,笔者遇到过一个死循环的问题,使用 sysrq 的内核线程栈回溯功能终于找到死循环的函数。在另一个项目中,应用程序发生了 double free,运用内核的栈回溯功能,找到应用代码哪里发生了 double ...
使用JavaSE实现即时通讯项目,适合有一定的Java基础的用户编写,主要用到多线程...代码部分我添加了大量的注册,并且加了一些我在开发的过程中遇到的问题,都用特殊标记标注出来了,以此来警告自己下次不犯类似的错误。
安卓开发的期末项目,以二十四节气为主题的论坛贴。用安卓的布局作为前端,SpringBoot作为后端。 登录界面: 登录首先需要把sql中原有的数据清空,因为该校验先会在前端的内存数据进行校验的,校验完成之后才会校验...
用JAVA开发的一个小型的目录监视系统,系统会每5秒自动扫描一次需要监视的目录,可以用来监视目录中文件大小及文件增减数目的变化。 Java日期选择控件完整源代码 14个目标文件 内容索引:JAVA源码,系统相关,日历,...
本书精选了222个在C++程序设计中经常遇到的问题和典型功能,覆盖了实际开发中的各种需求,目的是帮助读者解决在C++学习和开发中经常遇到的实际问题,同时提高学习和开发的效率。本书涵盖了C++与C语言的区别和联系、...
本书精选了222个在C++程序设计中经常遇到的问题和典型功能,覆盖了实际开发中的各种需求,目的是帮助读者解决在C++学习和开发中经常遇到的实际问题,同时提高学习和开发的效率。本书涵盖了C++与C语言的区别和联系、...
《Visual C 开发实例大全(提高卷)》以开发人员在项目开发中经常遇到的问题和必须掌握的技术为核心,介绍了应用Visual C 进行程序开发各个方面的知识和技巧,主要包括Windows操作、鼠标和键盘相关、注册表、线程和...
《Visual C 开发实例大全(提高卷)》以开发人员在项目开发中经常遇到的问题和必须掌握的技术为核心,介绍了应用Visual C 进行程序开发各个方面的知识和技巧,主要包括Windows操作、鼠标和键盘相关、注册表、线程和...
《Visual C 开发实例大全(提高卷)》以开发人员在项目开发中经常遇到的问题和必须掌握的技术为核心,介绍了应用Visual C 进行程序开发各个方面的知识和技巧,主要包括Windows操作、鼠标和键盘相关、注册表、线程和...