- 浏览: 781295 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (360)
- Java (101)
- JPA/Hibernate (10)
- Spring (14)
- Flex/BlazeDS (37)
- Database (30)
- Lucene/Solr/Nutch (0)
- Maven/Ant (25)
- CXF/WebService (3)
- RPC/RMI/SOAP/WSDL (1)
- REST (6)
- TDD/BDD/JUnit (1)
- Servlet/JSP (2)
- AI/MachineLearning (3)
- Resource (1)
- 字符编码 (2)
- OOA/OOPS/UML (5)
- DesignPattern (8)
- 算法与数据结构 (11)
- Web&App Server (13)
- 并发&异步&无阻塞 (7)
- Entertainment (4)
- JavaScript/ExtJS (45)
- CodeStyle&Quality (1)
- svn/git/perforce (8)
- JSON (2)
- JavaScriptTesting (4)
- Others (6)
- RegularExpression (2)
- Linux/Windows (12)
- Protocal (2)
- Celebrities (1)
- Interview (1)
- 计算机语言 (1)
- English (2)
- Eclipse (5)
- TimeZone/时区 (1)
- Finance (1)
- 信息安全 (1)
- JMS/MQ (2)
- XSD/XML/DTD (3)
- Android (4)
- 投资 (3)
- Distribution (3)
- Excel (1)
最新评论
-
qdujunjie:
如果把m换成具体的数字,比如4或者5,会让读者更明白
m阶B树中“阶”的含义 -
java-admin:
不错,加油,多写点文章
关于Extjs的mixins和plugin -
xiehuaidong880827:
你好,我用sencha cmd打包完本地工程后,把app.js ...
ExtJS使用Sencha Cmd合并javascript文件为一个文件 -
KIWIFLY:
lwpan 写道inverse = "true&qu ...
Hibernate中什么时候使用inverse=true -
luedipiaofeng:
good
消除IE stop running this script弹出框
https://plumbr.eu/blog/java/when-and-how-to-use-a-threadlocal
As our readers might already have guessed, I deal with memory leaks on a daily basis. A particular type of the OutOfMemoryError messages has recently started catching my attention – the issues triggered by misused ThreadLocals have become more and more frequent. Looking at the causes for such leakages, I am starting to believe that more than half of those are caused by developers who either have no clue what they are doing or who are trying to apply a solution to the problems which it is not meant to solve.
Instead of grinding my teeth, I decided to open up the topic by publishing two articles, first of which you are currently reading. In the post I explain the motivation behind ThreadLocal usage. In the second post currently in progress I will open up the ThreadLocal bonnet and look at the implementation.
Let us start with an imaginary scenario in which ThreadLocal usage is indeed reasonable. For this, say hello to our hypothetical developer, named Tim. Tim is developing a webapp, in which there is a lot of localized content. For example a user from California would expect to be greeted with date formatted using a familiar MM/dd/yy pattern, one from Estonia on the other hand would like to see a date formatted according to dd.MM.yyyy. So Tim starts writing code like this:
After a while, Tim finds this to be boring and against good practices – the application code is polluted with such initializations. So he makes a seemingly reasonable move by extracting the DateFormat to an instance variable. After making the move, his code now looks like the following:
Happy with the refactoring results, Tim tosses an imaginary high five to himself, pushes the change to the repository and walks home. Few days later the users start complaining – some of them seem to get completely garbled strings instead of the former nicely formatted dates.
Investigating the issue Tim discovers that the DateFormat implementation is not thread safe. Meaning that in the scenario above, if two threads simultaneously use the formatCurrentDate() and formatFirstOfJanyary1970() methods, there is a chance that the state gets mangled and displayed result could be messed up. So Tim fixes the issue by limiting the access to the methods to make sure one thread at a time is entering at the formatting functionality. Now his code looks like the following:
After giving himself another virtual high five, Tim commits the change and goes to a long-overdue vacation. Only to start receiving phone calls next day complaining that the throughput of the application has dramatically fallen. Digging into the issue he finds out that synchronizing the access has created an unexpected bottleneck in the application. Instead of entering the formatting sections as they pleased, threads now have to wait behind one another.
Reading further about the issue Tim discovers a different type of variables called ThreadLocal. These variables differ from their normal counterparts in that each thread that accesses one (via ThreadLocal’s get or set method) has its own, independently initialized copy of the variable. Happy with the newly discovered concept, Tim once again rewrites the code:
Going through a process like this, Tim has through painful lessons learned a powerful concept. Applied like in the last example, the result serves as a good example about the benefits.
But the newly-found concept is a dangerous one. If Tim had used one of the application classes instead of the JDK bundled DateFormat classes loaded by the bootstrap classloader, we are already in the danger zone. Just forgetting to remove it after the task at hand is completed, a copy of that Object will remain with the Thread, which tends to belong to a thread pool. Since lifespan of the pooled Thread surpasses that of the application, it will prevent the object and thus a ClassLoader being responsible for loading the application from being garbage collected. And we have created a leak, which has a chance to surface in a good old java.lang.OutOfMemoryError: PermGen space form
Another way to start abusing the concept is via using the ThreadLocal as a hack for getting a global context within your application. Going down this rabbit hole is a sure way to mangle your application code with all kind of unimaginary dependencies coupling your whole code base into an unmaintainable mess.
As our readers might already have guessed, I deal with memory leaks on a daily basis. A particular type of the OutOfMemoryError messages has recently started catching my attention – the issues triggered by misused ThreadLocals have become more and more frequent. Looking at the causes for such leakages, I am starting to believe that more than half of those are caused by developers who either have no clue what they are doing or who are trying to apply a solution to the problems which it is not meant to solve.
Instead of grinding my teeth, I decided to open up the topic by publishing two articles, first of which you are currently reading. In the post I explain the motivation behind ThreadLocal usage. In the second post currently in progress I will open up the ThreadLocal bonnet and look at the implementation.
Let us start with an imaginary scenario in which ThreadLocal usage is indeed reasonable. For this, say hello to our hypothetical developer, named Tim. Tim is developing a webapp, in which there is a lot of localized content. For example a user from California would expect to be greeted with date formatted using a familiar MM/dd/yy pattern, one from Estonia on the other hand would like to see a date formatted according to dd.MM.yyyy. So Tim starts writing code like this:
public String formatCurrentDate() { DateFormat df = new SimpleDateFormat("MM/dd/yy"); return df.format(new Date()); } public String formatFirstOfJanyary1970() { DateFormat df = new SimpleDateFormat("MM/dd/yy"); return df.format(new Date(0)); }
After a while, Tim finds this to be boring and against good practices – the application code is polluted with such initializations. So he makes a seemingly reasonable move by extracting the DateFormat to an instance variable. After making the move, his code now looks like the following:
private DateFormat df = new SimpleDateFormat("MM/dd/yy"); public String formatCurrentDate() { return df.format(new Date()); } public String formatFirstOfJanyary1970() { return df.format(new Date(0)); }
Happy with the refactoring results, Tim tosses an imaginary high five to himself, pushes the change to the repository and walks home. Few days later the users start complaining – some of them seem to get completely garbled strings instead of the former nicely formatted dates.
Investigating the issue Tim discovers that the DateFormat implementation is not thread safe. Meaning that in the scenario above, if two threads simultaneously use the formatCurrentDate() and formatFirstOfJanyary1970() methods, there is a chance that the state gets mangled and displayed result could be messed up. So Tim fixes the issue by limiting the access to the methods to make sure one thread at a time is entering at the formatting functionality. Now his code looks like the following:
private DateFormat df = new SimpleDateFormat("MM/dd/yy"); public synchronized String formatCurrentDate() { return df.format(new Date()); } public synchronized String formatFirstOfJanyary1970() { return df.format(new Date(0)); }
After giving himself another virtual high five, Tim commits the change and goes to a long-overdue vacation. Only to start receiving phone calls next day complaining that the throughput of the application has dramatically fallen. Digging into the issue he finds out that synchronizing the access has created an unexpected bottleneck in the application. Instead of entering the formatting sections as they pleased, threads now have to wait behind one another.
Reading further about the issue Tim discovers a different type of variables called ThreadLocal. These variables differ from their normal counterparts in that each thread that accesses one (via ThreadLocal’s get or set method) has its own, independently initialized copy of the variable. Happy with the newly discovered concept, Tim once again rewrites the code:
public static ThreadLocal df = new ThreadLocal() { protected DateFormat initialValue() { return new SimpleDateFormat("MM/dd/yy"); } }; public String formatCurrentDate() { return df.get().format(new Date()); } public String formatFirstOfJanyary1970() { return df.get().format(new Date(0)); }
Going through a process like this, Tim has through painful lessons learned a powerful concept. Applied like in the last example, the result serves as a good example about the benefits.
But the newly-found concept is a dangerous one. If Tim had used one of the application classes instead of the JDK bundled DateFormat classes loaded by the bootstrap classloader, we are already in the danger zone. Just forgetting to remove it after the task at hand is completed, a copy of that Object will remain with the Thread, which tends to belong to a thread pool. Since lifespan of the pooled Thread surpasses that of the application, it will prevent the object and thus a ClassLoader being responsible for loading the application from being garbage collected. And we have created a leak, which has a chance to surface in a good old java.lang.OutOfMemoryError: PermGen space form
Another way to start abusing the concept is via using the ThreadLocal as a hack for getting a global context within your application. Going down this rabbit hole is a sure way to mangle your application code with all kind of unimaginary dependencies coupling your whole code base into an unmaintainable mess.
发表评论
-
sapjco3 notes
2019-03-21 14:51 1089sapjco https://support.sap.com/ ... -
使用RestTemplate发送post JSON请求
2019-01-12 17:30 4566private final String BASE_URL = ... -
使用RestTemplate发送post JSON请求
2019-01-12 17:30 3380private final String BASE_URL = ... -
Spring线程池ThreadPoolTaskExecutor
2018-08-06 09:51 1775<!-- spring thread pool ex ... -
Spring注解事物@Transactional不工作
2018-08-02 18:50 2536“In proxy mode (which is the de ... -
创建前缀索引报长度超出错误
2018-07-25 15:44 1642表结构定义如下: CREATE TABLE `sku` ( ` ... -
Mysql Varchar字符长度
2018-07-25 15:23 1291`sku_name` VARCHAR(200) NOT NUL ... -
使用 Spring RestTemplate 发送 post 请求
2018-07-23 18:49 11623注意点: 1)使用MultiValueMap设置入参,不要使 ... -
Java动态代理Dynamic Proxy
2018-07-21 16:33 723JAVA学习篇--静态代理VS动态代理 https://blo ... -
分布式实时日志分析解决方案 ELK 部署架构
2018-07-20 09:52 1138原文链接:http://www.importn ... -
为什么HashMap容量一定要为2的幂呢?
2018-07-19 10:07 1652原文链接:https://blog.csdn.net/wang ... -
为什么计算HashCode时通常选择31这个数?
2018-07-19 10:05 1329摘自http://www.importnew.com/2208 ... -
jackson自定义序列化和反序列化
2018-07-10 18:47 2174原文链接:https://blog.csdn.net/liu ... -
Pay special attention when modifying online running system
2017-06-23 10:25 0Never remove any properties, me ... -
Map中的Null key, Null Value
2017-06-14 10:52 1878ConcurrentHashMap的key和value都不能为 ... -
Java语法糖
2017-06-05 20:03 476Java语法糖之foreach http://www.imp ... -
Java集合相关
2017-05-24 17:55 0Java集合框架:ArrayList http://www. ... -
Java数据类型的转换:隐式(自动)转换与强制转换
2017-05-14 10:46 0http://blog.csdn.net/u011240877 ... -
分布式开放消息系统(RocketMQ)的原理与实践
2017-05-07 19:55 669分布式开放消息系统(RocketMQ)的原理与实践 http ... -
面试知识点复习(Interview knowledge review)
2017-05-07 18:39 0JVM,多线程相关知识 http://darrenzhu.it ...
相关推荐
ThreadLocal入门教程。 讲解了线程安全和ThreadLocal的使用的基本知识。
ThreadLocal
理解ThreadLocal 理解ThreadLocal 理解ThreadLocal 理解ThreadLocal
ThreadLocal应用示例及理解,这个写了相关的示例,可以参考一下。
学习ThreadLocal,了解其中的原理,以及学习其中的优点!避免坑点!!
怎样选择并行处理:选择Parallel.ForEach 还是 PLINQ ?
DbUTils中用ThreadLocal类
正确理解ThreadLocal.pdf
主要介绍ThreadLocal的原理,实例分析以及注意事项
Synchronized与ThreadLocal
ThreadLocal的几种误区ThreadLocal的几种误区ThreadLocal的几种误区
java 简单的ThreadLocal示例
本例以序列号生成的程序为例,展示ThreadLocal的使用
设计模式及ThreadLocal详细讲解资料,想要学习java或者提升自己技术的同学可以下载观看
ThreadLocal保证一个类的实例变量在各个线程中都有一份单独的拷贝, 从而不会影响其他线程中的实例变量
详解java底层实现原理,ThreadLocal底层实现的数据结构,为什么不会导致内存泄露
JDBC事务的封装和Threadlocal实例,参考博客:http://blog.csdn.net/daijin888888/article/details/50988053
ThreadLocal源码分析,主要有ThreadLocal源码以及ThreadLocal的内部结构在jdk8前后的变化