首先来看下多线程处理的流程:
在来看下:httpClient请求工具方法:
public static String sendGetRequest(String reqURL, String decodeCharset) throws IOException {
long responseLength = 0; // 响应长度
String responseContent = null; // 响应内容
HttpClient httpClient = new DefaultHttpClient(); // 创建默认的httpClient实例
HttpGet httpGet = new HttpGet(reqURL); // 创建org.apache.http.client.methods.HttpGet
try {
HttpResponse response = httpClient.execute(httpGet); // 执行GET请求
HttpEntity entity = response.getEntity(); // 获取响应实体
if (null != entity) {
responseLength = entity.getContentLength();
responseContent = EntityUtils.toString(entity,
decodeCharset == null ? "UTF-8" : decodeCharset);
EntityUtils.consume(entity); // Consume response content
}
logger.debug("请求地址: " + httpGet.getURI());
logger.debug("响应状态: " + response.getStatusLine());
logger.debug("响应长度: " + responseLength);
logger.debug("响应内容: " + responseContent);
if(response.getStatusLine().getStatusCode() != 200) {
throw new RuntimeException("HTTP请求响应码为:"+response.getStatusLine().getStatusCode());
}
} catch (ClientProtocolException e) {
logger.debug("该异常通常是协议错误导致,比如构造HttpGet对象时传入的协议不对(将'http'写成'htp')或者服务器端返回的内容不符合HTTP协议要求等,堆栈信息如下"
+ e);
throw e;
} catch (ParseException e) {
logger.debug(e.getMessage() + e);
throw e;
} catch (IOException e) {
logger.debug("该异常通常是网络原因引起的,如HTTP服务器未启动等,堆栈信息如下" + e);
throw e;
} finally {
httpClient.getConnectionManager().shutdown(); // 关闭连接,释放资源
}
return responseContent;
我们来个测试方法,请求一个请求不通的地址看看:
public static void main(String[] args) {
long startTime=System.currentTimeMillis();
try{
System.out.println("开始时间:"+startTime);
String url="http://10.128.89.2:8080/test";
sendGetRequest(url, "utf-8");
long endTime=System.currentTimeMillis();
System.out.println("结束时间:"+endTime);
System.out.println("耗时:"+(endTime-startTime)/1000);
}catch(Exception e){
e.printStackTrace();
long endTime=System.currentTimeMillis();
System.out.println("结束时间:"+endTime);
System.out.println("耗时:"+(endTime-startTime)/1000);
}
}
运行结果如下:
从这个我们知道,HttpClient链接超时的默认时间是21S。
那么我上面的代码也没有写响应超时,那响应超时默认时间是多少呢?
我们来个接口,在接口里面线程休眠1000000000毫秒
@Controller
@RequestMapping(value = "/test")
public class TestController extends BaseController {
@RequestMapping(value = "/check", method = RequestMethod.GET)
public void check(HttpServletRequest request, HttpServletResponse response) {
try{
Thread.sleep(1000000000);
}catch(Exception e){
e.printStackTrace();
}
}
}
如果现在运行测试方法,因为该接口需要很长时间后才会响应。那么HttpClient请求方是一直在等待着响应,从而证实了一点,HttpClient默认无响应超时。
这种现象如果在多线程环境中,那么就是致命的。因为主线程在等待子线程处理完成,而子线程一直在等待Http响应。在复杂的网络环境中,可能会由于某种原因,永远都不会有响应,那么线程永远的等待。所以我们会以为,怎么线程死了。
所以在用HttpClient时候,最好设置个响应超时。
(本文由:阿中提供,版权所有,盗版必究,联系QQ:568017880,后续)