东营网站建设费用,网站开发综合设计报告,高职两学一做专题网站,室内设计效果图软件手机版使用threadlocal正如我们的读者可能已经猜到的那样#xff0c;我每天都会处理内存泄漏。 最近#xff0c;一种特殊类型的OutOfMemoryError消息开始引起我的注意-滥用ThreadLocals引发的问题变得越来越频繁。 在查看此类泄漏的原因时#xff0c;我开始相信其中一半以上是由于… 使用threadlocal 正如我们的读者可能已经猜到的那样我每天都会处理内存泄漏。 最近一种特殊类型的OutOfMemoryError消息开始引起我的注意-滥用ThreadLocals引发的问题变得越来越频繁。 在查看此类泄漏的原因时我开始相信其中一半以上是由于开发人员导致的他们要么不知道自己在做什么要么正试图对并非旨在解决的问题采用解决方案。 。 我决定不发表文章而是发表两篇文章来打开这个话题您目前正在阅读第一篇。 在帖子中我解释了ThreadLocal使用背后的动机。 在当前正在进行的第二篇文章中我将打开ThreadLocal帽子并查看实现。 让我们从一个虚构的场景开始其中ThreadLocal的使用确实是合理的。 为此请与我们的假设开发人员Tim打个招呼。 蒂姆Tim正在开发一个Webapp其中包含许多本地化内容。 例如来自加利福尼亚的用户可能希望使用熟悉的MM / dd / yy模式格式化日期而来自爱沙尼亚的用户则希望看到根据dd.MM.yyyy格式化的日期。 因此Tim开始编写如下代码 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));} 过了一会儿Tim觉得这很无聊并且违反了良好做法–应用程序代码被此类初始化污染了。 因此他通过将DateFormat提取到实例变量中采取了看似合理的措施。 采取行动之后他的代码现在如下所示 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));} Tim对重构结果感到满意Tim向自己扔了一个假想的高五将更改推送到存储库中然后回家。 几天后用户开始抱怨–其中一些字符串似乎完全乱码而不是以前格式正确的日期。 研究问题Tim发现DateFormat实现不是线程安全的。 这意味着在上述情况下如果两个线程同时使用formatCurrentDate和formatFirstOfJanyary1970方法则状态可能会混乱显示的结果可能会混乱。 因此Tim通过限制对方法的访问以确保一次输入一个线程进入格式化功能来解决此问题。 现在他的代码如下所示 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));} 在给自己另一个虚拟的高五后蒂姆做出了改变并去了一个漫长的假期。 第二天才开始收到电话抱怨应用程序的吞吐量急剧下降。 深入研究问题后他发现同步访问已在应用程序中造成了意外的瓶颈。 现在线程不必再随意输入格式化部分了而必须彼此等待。 进一步阅读该问题Tim发现了另一种类型的变量ThreadLocal 。 这些变量与普通变量不同因为每个访问一个线程通过ThreadLocal的get或set方法的线程都有其自己的独立初始化的变量副本。 对于新发现的概念感到满意Tim再次重写了代码 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));} 经过这样的过程蒂姆通过痛苦的教训学到了一个强大的概念。 像在最后一个示例中那样应用后结果可以很好地说明收益。 但是新发现的概念很危险。 如果Tim使用了应用程序类之一而不是引导类加载器加载的JDK捆绑的DateFormat类那么我们已经处在危险区域。 只是忘记在手头的任务完成后将其删除该对象的副本将保留在线程中该线程通常属于线程池。 由于池化线程的寿命超过了应用程序的寿命因此它将防止对象被垃圾回收从而防止ClassLoader负责加载应用程序。 而且我们创建了一个泄漏有机会以一种很好的旧java.lang.OutOfMemoryErrorPermGen空间形式浮出水面。 另一种开始滥用该概念的方法是通过使用ThreadLocal作为在应用程序中获取全局上下文的黑客。 顺其自然这是一种处理应用程序代码的可靠方法它具有各种无法想象的依赖关系从而将整个代码库陷入难以维护的混乱之中。 参考 何时以及如何使用我们的JCG合作伙伴 Nikita Salnikov Tarnovski 来自Plumbr博客 的ThreadLocal 。 翻译自: https://www.javacodegeeks.com/2013/10/when-and-how-to-use-a-threadlocal.html使用threadlocal