java threadlocal 缺点_Java的ThreadLocal如何在后台实现?

小编典典

这里的所有答案都是正确的,但是有些令人失望,因为它们多少掩盖了聪明ThreadLocal的实现是多么的明智。我只是在寻找源代码,ThreadLocal并且对它的实现方式印象深刻。

天真的实现

如果我要求您ThreadLocal在javadoc中描述的给定API的基础上实现一个类,该怎么办?最初的实现可能是ConcurrentHashMap使用Thread.currentThread()作为其密钥。这样会很好地工作,但确实有一些缺点。

线程争用- ConcurrentHashMap是一个非常聪明的类,但是它最终仍必须处理防止多个线程以任何方式破坏它,并且如果不同的线程有规律地命中它,将会降低速度。

即使在线程完成并且可以进行GC处理后,它仍永久保持指向线程和对象的指针。

GC友好的实现

好的,再试一次,让我们使用弱引用来处理垃圾回收问题。处理WeakReferences可能会造成混淆,但是使用像这样构建的地图应该足够了:

Collections.synchronizedMap(new WeakHashMap())

或者,如果我们使用的是番石榴(应该是!):

new MapMaker().weakKeys().makeMap()

这意味着一旦没有其他人抓住线程(暗示线程已完成),就可以对键/值进行垃圾收集,这是一种改进,但仍无法解决线程争用问题,这意味着到目前为止,我们ThreadLocal还不是全部令人赞叹的一堂课。此外,如果有人决定在Thread完成后保留对象,那么就永远不会对它们进行GC处理,因此即使我们的对象现在在技术上无法到达,也不会对其进行GC处理。

聪明的实现

我们一直在考虑ThreadLocal将线程映射为值,但是也许这实际上并不是正确的思考方式。与其将其视为从Threads到每个ThreadLocal对象中的值的映射,不如将其视为ThreadLocal对象到

每个Thread中的

值的映射怎么办?如果每个线程都存储了该映射,而ThreadLocal仅提供了该映射的一个不错的接口,我们可以避免以前实现中的所有问题。

一个实现看起来像这样:

// called for each thread, and updated by the ThreadLocal instance

new WeakHashMap()

此处无需担心并发性,因为只有一个线程将访问此映射。

Java开发人员在这里比我们有一个主要优势-他们可以直接开发Thread类并向其添加字段和操作,而这正是他们所做的。

/* ThreadLocal values pertaining to this thread. This map is maintained

* by the ThreadLocal class. */

ThreadLocal.ThreadLocalMap threadLocals = null;

正如评论所暗示的,确实是ThreadLocal对象为此跟踪的所有值的私有包映射Thread。的实现ThreadLocalMap不是WeakHashMap,而是遵循相同的基本协定,包括通过弱引用来持有其密钥。

ThreadLocal.get() 然后实现如下:

public T get() {

Thread t = Thread.currentThread();

ThreadLocalMap map = getMap(t);

if (map != null) {

ThreadLocalMap.Entry e = map.getEntry(this);

if (e != null) {

@SuppressWarnings("unchecked")

T result = (T)e.value;

return result;

}

}

return setInitialValue();

}

而ThreadLocal.setInitialValue()像这样:

private T setInitialValue() {

T value = initialValue();

Thread t = Thread.currentThread();

ThreadLocalMap map = getMap(t);

if (map != null)

map.set(this, value);

else

createMap(t, value);

return value;

}

本质上, 在此线程中

使用地图可以容纳我们所有的ThreadLocal对象。这样,我们永远不必担心其他线程中的值(ThreadLocal字面上只能访问当前线程中的值),因此没有并发问题。此外,一旦Thread完成,其映射将自动进行GC处理,并且将清除所有本地对象。即使将Thread其保留,ThreadLocal对象也会被弱引用保留,并且一旦ThreadLocal对象超出范围,就可以将其清除。

不用说,这个实现给我留下了深刻的印象,它很好地解决了很多并发问题(可以利用作为核心Java的一部分,但这是可以原谅的,因为它是一个非常聪明的类),并且允许快速和对仅一次需要一个线程访问的对象的线程安全访问。

tl; dr ThreadLocal的实现非常酷,并且比您乍看之下要快/聪明得多。

如果您喜欢这个答案,您可能也会喜欢我(不那么详细)的讨论ThreadLocalRandom。

2020-09-15

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

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

相关文章

第10步 (1)logback.xml日志配置(2) ftp(上传文件)服务器配置(3) idea注入和自动编译配置(4)项目提交gitee(5)fe助手和restlet client

****************************************************************************************************************************************** 1.直接复制 logback.xml 比较简单 <?xml version"1.0" encoding"UTF-8"?> <configuratio…

第11步 git推送失败 用户模块开发

别忘了git push ************************************************************************************************************************************* 1. 用户模块开发 共11个接口 用户 status 0 则是正确响应 其他1等是错误 用户信息是session中拿过来的 use…

java 继承 实现 会重写 方法吗_java 中继承,组合,重载,重写的实现原理 (转)...

我们知道&#xff0c;继承&#xff0c;组合&#xff0c;重载&#xff0c;重写是java语言的面向对象实现的基本特征。 那么在java内部&#xff0c;究竟是如何实现这些面对对象的基本特征的呢&#xff1f;继承和组合是面向对象中代码复用的主要实现方式&#xff0c;他们可以达到类…

Java 调用EXE

转载自 Java 调用EXE 使用Runtime.getRuntime().exec()方法可以在java程序里运行外部程序. 该方法有6个可访问版本: 1.exec(String command) 2.exec(String command, String envp[], File dir) 3.exec(String cmd, String envp[]) …

基于SignalR的消息推送与二维码描登录实现

1 概要说明 使用微信扫描登录相信大家都不会陌生吧&#xff0c;二维码与手机结合产生了不同应用场景&#xff0c;基于二维码的应用更是比较广泛。为了满足ios、android客户端与web短信平台的结合&#xff0c;特开发了基于SinglarR消息推送机制的扫描登录。本系统涉及到以下知识…

Java调用exe阻塞

转载自 Java调用exe阻塞 今天遇到了个奇怪的问题&#xff0c;用VC写了个小程序&#xff0c;编译成exe文件&#xff0c;然后用Java去调&#xff0c;居然卡住不运行了。如果双击这个exe程序&#xff0c;单独让它运行&#xff0c;是可以的&#xff0c;那么为什么用Java调用就不好…

java中iscontinue意思_Java 中return、continue和break的区别

写在前面&#xff1a;适合Java初学者&#xff0c;大神就别来了。今天同事突然问我return和break的区别&#xff0c;以前觉得随口都能说出来的东西&#xff0c;今天突然卡了&#xff0c;记得模模糊糊&#xff0c;只能说出个大概&#xff0c;所以这里做一个总结&#xff0c;还是那…

第13步 用户模块前端(Admin)

bootstrap 就不用谢css样式 了 都写好了 http://www.bootcss.com/ https://www.bootcdn.cn/ <meta charset"utf-8"> <!-- 防止网站在手机端看变形了 --> <meta name"viewPort" content"widthdevice-width,initial…

ASP.NET Core 静态文件及JS包管理器(npm, Bower)的使用

在 ASP.NET Core 中添加静态文件 虽然ASP.NET主要大都做着后端的事情&#xff0c;但前端的一些静态文件也是很重要的。在ASP.NET Core中要启用静态文件&#xff0c;需要Microsoft.AspNetCore.StaticFiles组件。可以通过Nuget添加&#xff0c;或者在project.json配置文件中添加&…

Java 正则表达式匹配模式[贪婪型、勉强型、占有型]

转载自 Java 正则表达式匹配模式[贪婪型、勉强型、占有型]Greediness&#xff08;贪婪型&#xff09;&#xff1a;最大匹配 X?、X*、X、X{n&#xff0c;} 是最大匹配。例如你要用 “<.>” 去匹配 “a<tr>aava </tr>abb”&#xff0c;也许你所期待的结果是想…

新闻发布项目——分页公共类(PageUitl )

package bdqn.newsManageServlet.Util; /*** 分页的类* author Administrator**/ public class PageUitl {private int pagesize;//页大小private int pageindex1;//页码private int recordCount;//总记录数private int totalPageCount;//总页数//计算总页数public int getTota…

java代码配置 mybatis_配置简介(MyBatis源码篇)

1 SqlSessionFactoryBuilder#上篇例子中&#xff0c;我们以SqlSessionFactoryBuilder去创建SqlSessionFactory, 那么&#xff0c;我们就先从SqlSessionFactoryBuilder入手&#xff0c; 咱们先看看源码是怎么实现的。SqlSessionFactoryBuilder源码片段&#xff1a;public class …

js 方法传递对象参数

js 方法传递对象参数 2017年12月06日 16:35:39 qq_26676207 阅读数&#xff1a;7696 版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/qq_26676207/article/details/78732117 第一步&#xff1a; //通过JSON.stringify()方…

Java8中 Date和LocalDateTime的相互转换

转载自 Java8中 Date和LocalDateTime的相互转换一.在Java 8中将Date转换为LocalDateTime 方法1: 将Date转换为LocalDatetime&#xff0c;我们可以使用以下方法&#xff1a; 1.从日期获取ZonedDateTime并使用其方法toLocalDateTime&#xff08;&#xff09;获取LocalDateTime 2…

java 时分秒格式小时8_Java里得到00:00:00格式的时分秒的Timestamp

复制代码 代码如下:import java.sql.Timestamp;import java.text.SimpleDateFormat;import java.util.TimeZone;public class Test {public static void main(String[] args) {SimpleDateFormat sdf new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");long t System.cu…

免费开源的 .NET 分布式组件库 Exceptionless Foundatio

前言 在互联网时代&#xff0c;分布式应用、系统变得越来越多&#xff0c;我们在使用 .Net 技术构建分布式系统的时候&#xff0c;需要使用到一些组件或者是助手库来帮助我们提高生产力以及应用程序解耦&#xff0c;但是纵观.Net圈&#xff0c;能够符合要求的这样的组件并不是很…

Java 8 中 Date与LocalDateTime、LocalDate、LocalTime互转

转载自 Java 8 中 Date与LocalDateTime、LocalDate、LocalTime互转Java 8中 java.util.Date 类新增了两个方法&#xff0c;分别是from(Instant instant)和toInstant()方法 // Obtains an instance of Date from an Instant object. public static Date from(Instant instant) …

mysql 删除过期日志_【转】对mysql日志进行操作的总结包括 启用,过期自动删除 等...

近段时间一直在研究mysql的日志系统,在网上看了N多mysql日志操作的文章&#xff0c;但都过于零乱&#xff0c;为了让自己以后不再搞忘&#xff0c;特作出以下总结&#xff1a;1. 以前我错误的认为mysql的日志可以恢复到任何时间的状态&#xff0c;其实并不是这样&#xff0c;这…