该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2012-08-09
学习了,清晰易懂,谢谢
|
|
返回顶楼 | |
发表时间:2012-08-09
最后修改:2012-08-09
downpour 写道 jwx0925 写道 我们公司的应用(访问量很大)已经出现过几次这样的问题,由于ThreadLocal使用不当,造成系统频繁内存溢出。
ThreadLocal的Entry的弱引用问题,网上也有很多文章:http://blog.163.com/greencoat_man@126/blog/static/10261923520106410928943/ 其实,只要不泛滥使用ThreadLocal,正确的使用,一般情况下,是没有问题的。 即使是用线程池,内存溢出的可能性我认为也很小,不过我没有研究过web容器的线程池,结论不敢妄下。如果一个Web容器的线程池连ThreadLocal的问题都没有考虑到,这个Web容器的设计只能打不及格。 从原理上看,如果在线程池+ThreadLocal的场景下,如果不手工删除, 1)可能会发生内存泄漏,但是概率很小,基本可以不考虑。 2)一定会延长垃圾回收时间,降低内存使用率,但影响很不会大。 场景1:没有线程池的场景 1.用户A请求来了,创建一个新线程T1; 2.创建UserSession对象,将其绑定到ThrealLocal中; 3.完成用户请求,返回响应; 4.线程T1销毁; 5.ThreadLocal中T1所对应的UserSession元素移除,UserSession可被垃圾回收。 场景2:有线程池的场景 1.用户A请求来了,从线程池获取可用线程T1; 2.创建UserSession对象,将其绑定到ThrealLocal中; 3.完成用户请求,返回响应; 4.线程T1返回线程池; 5.ThreadLocal中T1所对应的UserSession元素不会移除,UserSession还不能被垃圾回收; 6.过了若干时间(一会儿)... 7.用户B请求来了,从线程池获取线程,发现T1可用,返回T1 8.创建用户B的UserSession对象,将其绑定到ThrealLocal中,ThreadLocal中 (T1,用户A UserSession)的项目 将被覆盖成(T1,用户B UserSession); 9.用户A的UserSession 可被垃圾回收。 对比场景1和场景2,我们发现用户A的UserSession 最终都是会被回收的,只不过场景1会“比较及时地”回收,而 场景2中,回收得不够及时。 如果应用中有很多东西都在放在ThreadLocal(有很多ThreadLocal变量),那么还是要考虑一下这种延长垃圾回收对内存的影响的。我给出一个公式: 引用 假设应用中有N个ThreadLocal的变量,线程池的大小为M,每个ThreadLocal变量占用内存平均为P,则因这种延迟
回收而战胜的内存最大值T为: T = N*M*P 举例来说,你的应用中有20个ThreadLocal变量 ,Web服务器的线程池最大线程数为 500,每个ThreadLocal变量平均大小为1K,则因延迟而造成的内存泄漏最大量为: 20*500*1K = 10M 注意以上是极端情况下的泄漏量,由于线程池本身有idle线程一段时间后自动销毁的机制,另考虑到线程池的线程复用率,并发性极高,因此实际的内存泄漏量要小很多,象上面的情况,我估计也就是1M左右吧。 由于手工清除ThreadLocal变量会让代码复杂性变高,因此一般情况下,是不用去考虑的,等真的发生了问题再去关注这块吧。 |
|
返回顶楼 | |
发表时间:2012-08-29
讨论很精彩。 这下差不多理解了ThreadLocal. 感谢啊
|
|
返回顶楼 | |
发表时间:2012-10-17
mazzystar 写道 stamen 写道 概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式:访问串行化,对象共享化。而ThreadLocal采用了“以空间换时间”的方式:访问并行化,对象独享化。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。
说的真好,赞一个 这个好像在陆舟的struts2 技术内幕看大过,难道楼主是陆舟大神。。。 |
|
返回顶楼 | |
发表时间:2012-10-18
jasshine 写道 mazzystar 写道 stamen 写道 概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式:访问串行化,对象共享化。而ThreadLocal采用了“以空间换时间”的方式:访问并行化,对象独享化。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。
说的真好,赞一个 这个好像在陆舟的struts2 技术内幕看大过,难道楼主是陆舟大神。。。 陆舟是我。楼主的总结其实也来源于网上,我之前的总结也是。我更多从源码角度解读,楼主通过实例解读。异曲同工而已。 |
|
返回顶楼 | |
发表时间:2012-10-21
downpour 写道 jasshine 写道 mazzystar 写道 stamen 写道 概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式:访问串行化,对象共享化。而ThreadLocal采用了“以空间换时间”的方式:访问并行化,对象独享化。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。
说的真好,赞一个 这个好像在陆舟的struts2 技术内幕看大过,难道楼主是陆舟大神。。。 陆舟是我。楼主的总结其实也来源于网上,我之前的总结也是。我更多从源码角度解读,楼主通过实例解读。异曲同工而已。 额。。。我买了您的那本struts2技术内幕,感觉写的真好,很有条理。什么时候也给我们写个spring技术内幕吧。 |
|
返回顶楼 | |
发表时间:2012-10-22
很精彩,也很使用,楼主辛苦。
|
|
返回顶楼 | |
发表时间:2013-02-07
学习了,通俗易懂
|
|
返回顶楼 | |
发表时间:2013-02-27
请问下LZ
《Spring 3.x企业应用开发实战》这本书适合什么人群看呢?我买了本《Spring技术内幕2》,看起来有点吃力,一开始就是讲底层代码。 请LZ给点意见 |
|
返回顶楼 | |
发表时间:2013-03-07
那几篇讲的都很好,多谢楼主,受益匪浅啊
|
|
返回顶楼 | |