-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
63 lines (46 loc) · 4.98 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="UTF-8">
<title>Kangyufeng-blog by kangyf3</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="stylesheets/normalize.css" media="screen">
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" type="text/css" href="stylesheets/stylesheet.css" media="screen">
<link rel="stylesheet" type="text/css" href="stylesheets/github-light.css" media="screen">
</head>
<body>
<section class="page-header">
<h1 class="project-name">Kangyufeng-blog</h1>
<h2 class="project-tagline">Httpclient静态单例模式在多线程下并发问题分析及解决</h2>
<a href="https://github.com/kangyf3/kangyufeng-blog" class="btn">View on GitHub</a>
<a href="https://github.com/kangyf3/kangyufeng-blog/zipball/master" class="btn">Download .zip</a>
<a href="https://github.com/kangyf3/kangyufeng-blog/tarball/master" class="btn">Download .tar.gz</a>
</section>
<section class="main-content">
<p>目前项目用到HttpClient 和其他系统的http接口进行交互,为了提高并发量,项目采用了线程池模型,但系统在运行一段时间后发现线程池的线程被占用完了,经过分析日志,实际上的并发只有几百条,后来进行的代码自检,找到了问题所在。</p>
<hr>
<p>private static final HttpClient httpclients = HttpClientUtils.httpclient;</p>
<p>代码在HttpClient初始化的时候考虑到对象频繁的创建会造成系统资源开销,因此采用了 static final 模式,加final 是为了保持调用对象不被修改提高安全性考虑,但当执行http请求是,根据系统日志分析,并发量不大的情况下线程被大量占用,分析静态对象模式和jvm原理并没有找到关于 static final 对象会存在竞争锁的问题,线程不会阻塞,于是进行了代码分析,</p>
<ul>
<li>
httpclient.executeMethod(postMethod);<br>
后来终于找到原因了,原来是本地httpclient设置时,最大连接数采用了默认设置的原因,而默认的最 大连接数只有2个,所以当有大量连接需要建立时,大多数连接只有等待。,这样当一个请求占用较大时间的时候,一个时段的并发只有2个,线程就被阻塞,HttpClient这个地方会有一个锁定,因此造成了线程大量被占用在等待中,并发较小,线程值线程被占用完</li>
</ul>
<p>解决方案:</p>
<pre><code> params.setDefaultMaxConnectionsPerHost(32);//very important!!
params.setMaxTotalConnections(256);//very important!!
</code></pre>
<p>设置httpclient默认连接数和最大连接数,保证并发量增大</p>
<p>第二种方案,可以考虑每次都new 一个httpClient,
当然两种方式都有利弊,使用者应该考虑自己系统的情况</p>
<p>这里需要讲一下 static 和final 以及单例模式,从jvm角度,当我们定义一个static 对象或者单例模式对象的时候,系统会在内存中为该对象开辟一块,在系统运行过程中这个内存栈一直不会改变,调用者使用对象都将指向该内存栈对象,获取调用对象运行。final 是为了锁定该对象,保持对象不变化(final不会锁定对象内的集合的数据),严格意义上这个锁定并不是我们理解的synchronized 即同步锁定,final只会组织对象的属性的改变,但不会阻止两次并发的访问,synchronized 能够保证synchronized 锁定的代码执行完成之后,对象才能释放出来,因此不能造成对象锁定,阻止并发,但HttpClient的连接数 被synchronized 了,所以造成了并发降低</p>
<p>当然,共用一个对象是线程不安全的,当一个static对象被一个线程改变了对象的属性,另一个线程中也将会改变,因此使用的时候要考虑 结合final使用,很多人会有疑问,我们常常采用的spring 默认的状态下不是单例模式吗,这样是否会线程不安全,当然是的,但是大家要知道,交给spring管理的bean都是一些功能函数,我们很少去使用这个bean的对象属性,这点大家也要注意(我们一般不会把数据对象bean交给spring管理),</p>
<p>参照帖子:<a href="http://www.cnblogs.com/lovingprince/archive/2009/09/03/2166308.html">http://www.cnblogs.com/lovingprince/archive/2009/09/03/2166308.html</a></p>
<footer class="site-footer">
<span class="site-footer-owner"><a href="https://github.com/kangyf3/kangyufeng-blog">Kangyufeng-blog</a> is maintained by <a href="https://github.com/kangyf3">kangyf3</a>.</span>
<span class="site-footer-credits">This page was generated by <a href="https://pages.github.com">GitHub Pages</a> using the <a href="https://github.com/jasonlong/cayman-theme">Cayman theme</a> by <a href="https://twitter.com/jasonlong">Jason Long</a>.</span>
</footer>
</section>
</body>
</html>