何时以及如何使用ThreadLocal

正如我们的读者可能已经猜到的那样,我每天都在处理内存泄漏。 最近,一种特殊类型的OutOfMemoryError消息开始引起我的注意-滥用ThreadLocals触发的问题变得越来越频繁。 在查看此类泄漏的原因时,我开始相信其中一半以上是由于开发人员导致的,他们要么不知道自己在做什么,要么正试图对并非旨在解决的问题采用解决方案。 。

我决定不发表文章,而是发表两篇文章来打开这个话题,您目前正在阅读第一篇。 在帖子中,我解释了ThreadLocal使用背后的动机。 在当前正在进行的第二篇文章中,我将打开ThreadLocal帽子并查看实现。

让我们从一个虚构的场景开始,其中ThreadLocal的使用确实是合理的。 为此,请与我们的假设开发人员Tim打个招呼。 蒂姆正在开发一个Web应用程序,其中包含许多本地化内容。 例如,来自加利福尼亚的用户可能希望使用熟悉的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.OutOfMemoryError:PermGen空间形式浮出水面。

另一种开始滥用该概念的方法是通过使用ThreadLocal作为在应用程序中获取全局上下文的黑客。 克服这个难题是确保应用程序代码具有各种无法想象的依赖关系的可靠方式,将整个代码库耦合到一个无法维护的混乱中。

参考: 何时以及如何使用我们的JCG合作伙伴 Nikita Salnikov Tarnovski (来自Plumbr博客) 的ThreadLocal 。

翻译自: https://www.javacodegeeks.com/2013/10/when-and-how-to-use-a-threadlocal.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/366773.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux redis安装使用,linux安装redis

Linux(CentOS)中Redis介绍、安装、使用【一篇就够】2018-05-13 13:36:16 sjmz30071360 阅读数 1590更多分类专栏: redis版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。一、介绍Redis is…

用three.js写一个简单的3D射门游戏

这个小游戏很简单,一共由3个部分构成。1个平面(球场),1个球体(足球)还有一个立方体(球门)。 上个图给你们感受一下简陋的画风(掘金最高上传5M图片,原来图片都…

100份Spring面试问答-最终名单(PDF下载)

上次更新时间:2019年2月11日 这是有关Spring框架的一些最重要问题的摘要,在面试或面试测试过程中可能会要求您回答这些问题! 您无需担心下一次面试的机会,因为Java Code Geeks在这里为您服务! 您可能会被问到的大多数…

3.1 unittest简介

3.1 unittest简介 前言 熟悉java的应该都清楚常见的单元测试框架Junit和TestNG。python里面也有单元测试框架-unittest,相当于是一个python版的junit。python里面的单元测试框架除了unittest,还有一个pytest框架,这个用的比较少,后面有空再继…

织梦其他模型使用联动类型地区联动

官方模型的联动类型只能模型是在【独立模型】或者官方默认的【分类信息】模型下使用,其他模型下使用无效,我们来让联动类型支持所有模型。 添加联动地区类型字段 内容模型管理 - 文章模型(或者其他模型) - 添加新字段 字段名称 和 数据类型 千万别搞错了…

linux修改组的选项名字为,Linux用户、组及权限管理浅析

一、用户和组1.用户系统用来认证(Authentication),授权(Authorization),审计(Autition)的帐号。通过登录用户来登录系统。操作系统通过登录不同的用户来调用相对应权限的进程或程序,也可以说,用户是能获取系统资源的权限集合。2.用…

如何在 vue-cli v3.0 中使用 SCSS/SASS

在项目中使用 SCSS/SASS 进行样式编写无疑会节省很多开发样式的时间。关于如何在 vue-cli v3.0 中使用 SCSS/SASS,这里提供三种方案。前提是在使用 vue-cli 生成项目时勾选了 CSS Pre-processors (CSS预处理器),否则无法在项目中直接使用。 方案一&…

使用IntelliJ IDEA进行热部署

最近,在PrimeFaces论坛PrimeFaces IDE Poll中进行了投票,以投票赞成用于开发PrimeFaces应用程序的最佳IDE。 最多人投票支持NetBeans。 NetBeans和Eclipse是免费的IDE。 我最喜欢的IDE IntelliJ IDEA Ultimate不是免费的,我认为这就是为什么在…

创梦天地关嵩:借力腾讯云,打造文娱新生态——云+未来峰会回顾

欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 今年腾讯云未来峰会主题的关键词是“焕启”,这是包含无限希望的两个字,让人倍感振奋。“焕启”是什么意思?在我的理解中,“焕启”本身就是激活,激…

领域模型学习笔记

别在领域模型迷失了自己转载于:https://www.cnblogs.com/mySerilBlog/p/9914375.html

【缓存清理工具】缓存清理软件_电脑缓存清理软件

产品介绍 有很多种比如来自网页和windows等,缓存如果不经常清理会使你的机器运行速度变慢,缓存清理工具可以帮你最多程度的清理垃圾文件而且速度也很快,有了它的帮助让你爱机清理彻底,运行更加顺畅!主要能清理:所有应…

c语言转义字符空格符号,C语言 转义符\t占用几个空格

这个问题,在你学习编程过程中可能会考虑到,有时为了字节对齐而使用转义符中\t,但是到底\t占用几个空格呢?下面我们首先通过程序来体验下,然后在总结#include int main(){printf("123456\t123\t45\n");printf("12\t…

检测Maven依赖中介

从Maven 2.0.9开始,向Maven添加了一个新功能,称为依赖中介。 依赖关系中介是Maven在特定情况下在依赖关系树中多次出现依赖关系时用来解决项目依赖关系的技术。 通常,这发生在通过项目的依赖关系链接的传递依赖关系上。 在这种情况下&#xf…

简单的节流函数throttle

在实际项目中,总会遇到一些函数频繁调用的情况,比如window.resize,mouseover,上传进度类似的触发频率比较高的函数,造成很大的性能损耗,这里可以使用节流函数来进行性能优化,主要是限制函数被频…

[探索] 利用promise做一个请求锁

在最近开发小程序的过程中,遇到一个需求,就是请求的时候header需要带上accessToken, accessToken是通过登陆接口返回的参数,可能会出现过期的情况,则需要重新登陆,所以每次加载小程序都会进行一次本地储存的accessToke…

c语言网上找程序组合,C语言程序我同学说在网上下的一章一章的小说组合成一个太麻烦,于是 爱问知识人...

我同学说在网上下的一章一章的小说组合成一个太麻烦,于是我突发奇想要做一个把记事本中的内容按顺序连接起来的程序,但是运行不了,我怀疑是读写时候指针搞错了,情大侠们帮我看看,小弟感激不尽!#include#inc…

用于J2EE开发的Cloud IDE

随着许多传统软件工具进入云计算,我想看看它们与传统工具的比较。 我的兴趣是Java EE技术,并开始寻找一种云服务,该服务使我能够开发,测试和部署Java EE应用程序。 我很快发现,许多云IDE是为Web前端技术(例…

【Python】[02]初识Python

Python3的下载安装 根据书上的推荐,我将学习和使用Python3版本,从www.python.org网站,根据对应的操作系统,下载合适的Python版本即可 我的是64位系统,所以我选择的是Windows x86-64 executable installer 下载完成后双…

自己写了一个多行文本溢出文字补全的小库, 说不定你会用得到的

有些时候产品会有这么个需求,希望给文章或者帖子给一个摘要,最多3行,或者其它行数,超出3行会补上...。当然这种很简单,用css可以搞定。但是遇上要求多点的产品,希望补上的是...查看全文,这样的话…

C语言简单程序情话,给你一份程序员的“科技情话”,赶在双十一前脱单吧

说起程序员很多人第一印象都是呆板木讷但你们不知道程序员的浪漫花样给你一份程序员的“科技情话”赶在双十一前,和你暗恋的人表白吧~程序员的情书Void missing_you()For(timemeet_you;;time)Missing_you()自从遇见你,就没有一刻不想你-----------------…