ThreadLocal如何实现?

这是我上周的帖子的后续文章,在那篇文章中我解释了ThreadLocal用法的动机 。 从帖子中我们可以回想起,如果您希望每个线程都有一个独立初始化的变量副本,则ThreadLocal确实是一个很酷的概念。 现在,好奇的人可能已经开始问“我如何在Java中实现这样的概念”?

否则,您可能会觉得这不是一个有趣的话题–毕竟,您在这里所需的只是一张地图 ,不是吗? 在处理ThreadLocal <T>时 ,将解决方案实现为HashMap <Thread,T>并以Thread.currentThread()作为键似乎是明智的。 其实不是那么简单。 因此,如果您有五分钟的时间,请忍受我,我将指导您完成一个美丽的设计概念。

简单的HashMap解决方案的第一个明显问题是线程安全性。 由于HashMap并不是为支持并发使用而构建的,因此我们无法在多线程环境中安全地使用该实现。 幸运的是,我们不需要花很多时间来解决问题-ConcurrentHashMap <Thread,T>看起来像是天作之合。 检索的完全并发性和可调整的预期更新并发性正是我们首先需要的。

现在,如果您将基于ConcurrentHashMap的解决方案应用于JDK源代码中的ThreadLocal实现,则会带来两个严重的问题。

  • 首先,在Map结构中将线程作为键。 由于映射永远不会被垃圾回收,因此最终您将永远保持对Thread的引用,从而阻止了该线程成为GCd。 不情愿的是,您在设计中造成了巨大的内存泄漏。
  • 第二个问题可能需要更长的时间才能浮出水面,但是即使在幕后进行了巧妙的分段以减少锁争用的机会, ConcurrentHashMap仍然承担同步开销。 在同步需求仍然存在的情况下,您仍然拥有一个结构,可能成为瓶颈的根源。

但是,让我们首先开始解决最大的问题。 如果我们的引用是指向相关线程的最后一个引用,则我们的数据结构需要允许对线程进行垃圾回收。 再次,第一个可能的解决方案是盯着我们–而不是通常引用对象,为什么不使用WeakReferences ? 因此,实现现在看起来类似于以下内容:

Collections.synchronizedMap(new WeakHashMap<Thread, T>())

现在,我们已经解决了泄漏问题–如果除我们之外没有人引用Thread ,则可以将其定型并进行垃圾回收。 但是我们仍然没有解决并发问题。 现在,解决方案实际上是关于跳出思路思考的样本。 到目前为止,我们已经将ThreadLocal变量视为映射到变量的Threads 。 但是,如果我们颠倒了思路,而是设想了一个解决方案,将ThreadLocal对象映射到每个Thread中的值,该怎么办? 如果每个线程都存储该映射,并且ThreadLocal只是该映射的接口,则可以避免同步问题。 更好的是,我们还避免了GC带来的问题!

确实,当我们打开ThreadLocalThread类的源代码时 ,我们看到这正是在JDK中实际实现该解决方案的方式:

public class Thread implements Runnable {ThreadLocal.ThreadLocalMap threadLocals = null;// cut for brevity
}
public class ThreadLocal<T> {static class ThreadLocalMap {// cut for brevity}ThreadLocalMap getMap(Thread t) {return t.threadLocals;}public T get() {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) {ThreadLocalMap.Entry e = map.getEntry(this);if (e != null)return (T) e.value;}return setInitialValue();}private T setInitialValue() {T value = initialValue();Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);return value;}// cut for brevity
}

因此,这里有它。 Thread类保留对ThreadLocal.ThreadLocalMap实例的引用,该实例是使用对键的弱引用构建的。 以相反的方式构建结构,因为我们的ThreadLocal只能访问当前线程中的值,所以我们完全避免了线程争用问题。 另外,当Thread完成工作时,映射可以进行垃圾回收,因此我们也避免了内存泄漏的问题。

希望您对设计有所了解,因为它确实是解决复杂问题的理想解决方案。 我确实认为阅读源代码是学习新概念的理想方式。 而且,如果您是Java开发人员,那么与阅读集成到JDK的Joshua Bloch和Doug Lea源代码相比,还有什么比这更好的获取知识的地方了?

参考: 如何实现ThreadLocal? 由我们的JCG合作伙伴 Nikita Salnikov Tarnovski在Plumbr Blog博客上获得。

翻译自: https://www.javacodegeeks.com/2013/11/how-is-threadlocal-implemented.html

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

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

相关文章

WPFの操作文件浏览框几种方式

WPFの操作文件浏览框几种方式 原文:WPFの操作文件浏览框几种方式方式1&#xff1a; 使用win32控件OpenFileDialog Microsoft.Win32.OpenFileDialog ofd new Microsoft.Win32.OpenFileDialog(); ofd.DefaultExt ".xml"; ofd.Filter "xml file|*.xml"; if…

为什么你应该尝试@reach/router

最近react-router的一个作者另外写了一个类react-router的组件 reach/router&#xff0c;尝试后感觉太棒了。如果你的项目只是web端的话我认为可以把你的react-router换掉了。下面是我到目前看到的所有非常好的点。 小&#xff0c;就4kb,压缩后比react-router小40kb左右。 更少…

android 浏览器 div穿透,解决IE 上重叠div 对 mouseover 事件的穿透方法之一

解决IE 下重叠div 对 mouseover 事件的穿透方法之一? ? ? ? 历经一天半的时间&#xff0c;我这前端的白痴终于想到了一个解决IE 下重叠div ?对 mouseover 事件的穿透方法。??现象&#xff1a; 两个并列关系的Div(没有父子关系)&#xff0c;但是两个Div在位置上面有重叠&…

类加载器工作机制

类加载器工作机制&#xff1a;1.装载&#xff1a;将Java二进制代码导入jvm中&#xff0c;生成Class文件。2.连接&#xff1a;a&#xff09;校验&#xff1a;检查载入Class文件数据的正确性 b&#xff09;准备&#xff1a;给类的静态变量分配存储空间 c&#xff09;解析&#xf…

webviewjavascriptbridge android ios,js与ios交互使用WebViewJavascriptBridge如何写多个函数

//js与webview交互初始化function setupWebViewJavascriptBridge(callback) {if (window.WebViewJavascriptBridge) {return callback(WebViewJavascriptBridge);}if (window.WVJBCallbacks) {return window.WVJBCallbacks.push(callback);}window.WVJBCallbacks [callback];v…

JavaFX中的塔防

我想长时间使用我的游戏引擎来编写《塔防》游戏&#xff0c;但是由于另一个小组努力创建JavaFX《塔防》游戏&#xff0c;所以我认为我宁愿创建另一款游戏。 从邮件列表中&#xff0c;我了解到不再开发其他游戏。 因此&#xff0c;我决定尝试一下。 塔防是一款非常适合基于图块…

CSS pointer-events属性的使用

楔子 在前端的开发中&#xff0c;我们都是直接与用户接触&#xff0c;应该尽量让用户感到操作畅快愉悦&#xff0c;获得类似native的感觉。其中动画是最常用的方法。 这里的需求是&#xff0c;弹层的设计&#xff0c;这个弹层希望可以像 native 上的弹层一样&#xff0c;点击…

海思NB-IOT的SDK看门狗的使用

1. 看门狗需要喂狗&#xff0c;如果自己写的任务一直运行&#xff0c;那么空闲任务无法运行会导致看门狗复位&#xff0c;来看下看门狗的机制&#xff0c;首先系统启动的时候创建了空闲任务 在这个函数里面void vTaskStartScheduler( void )创建了下面的空闲任务 xReturn xTas…

分布式Session框架

分布式Session框架 配置服务器&#xff0c;Zookeeper集群管理服务器可以统一管理所有服务器的配置文件共享这些Session存储在一个分布式缓存中&#xff0c;可以随时写入和读取&#xff0c;而且性能要很好&#xff0c;如Memcache&#xff0c;Tair。封装一个类继承自HttpSession&…

向您的JVM添加一些熵

能否生成真正的随机数取决于系统中的熵。 有人声称&#xff0c;这可以通过掷骰子来保证。 其他人认为&#xff0c;用此主体替换OpenJDK的java.math.Random.nextInt&#xff08;&#xff09;方法将有所帮助&#xff1a; public int nextInt() {return 14; }资料来源&#xff1a…

android源码多少行,Android源码资料

缺点&#xff1a;有时会访问不了优点&#xff1a;搜索方便&#xff0c;支持跳转引用)一个操作的小技巧&#xff0c;不想跳转引用的类覆盖当前页面&#xff0c;可以按下ctrl键点击。https://www.cnblogs.com/CVstyle/p/6395662.htmlhttps://www.jianshu.com/p/25a908c7eefaAndro…

Android初学第80天

Android初学第80天 20_MVVM 代码 BeatBox BeatBox.java package com.bignerdranch.android.beatbox;import android.content.Context; import android.content.res.AssetManager; import android.util.Log;import java.io.IOException; import java.util.ArrayList; import jav…

深入理解JavaScript之Event Loop

前言 最近阅读《高性能JavaScript》时&#xff0c;第六章谈到“通过定时器将JavaScript执行代码的控制权先让给浏览器用于更新UI状态&#xff0c;然后再将控制权交回给JavaScript代码&#xff0c;这样就可以使得页面更为流畅”&#xff0c;就联想到了之前理解的事件循环。 这…

使用EasyPoi导出Excel

Excel模板来自自己写死的一个excel模板&#xff0c;相当于是用户查询数据&#xff0c;数据填充到一个模板的Excel里&#xff0c;再导出Excel /*创建模板*/String a request.getSession().getServletContext().getRealPath("/resource/河南能源化工集团安全监控系统联网系统…

Hazelcast入门

7月&#xff0c;我写了一个博客向Java开发人员介绍erlang&#xff0c;重点介绍了这两种语言之间的一些异同。 erlang虚拟机具有许多令人印象深刻的内置功能&#xff0c;其中之一是它们独立于位置并且可以互相通信。 这意味着可以通过编写很少的代码行在VM之间同步数据。 如果您…

android手机最低内存,原神手机端需要哪些配置 手机端最低配置要求介绍

原神是一款由米哈游自主研发的全新开放世界冒险游戏&#xff0c;游戏最近迎来了pc端的首次测试&#xff0c;而且在不久之后就会开启原神手机端的公测版本&#xff0c;那么手机端需要什么配置呢&#xff1f;小编带来了详细的介绍。移动端预下载&#xff1a;9月25日下午16&#x…

AnswerOpenCV一周佳作欣赏(0615-0622)

一、How to make auto-adjustments(brightness and contrast) for image Android Opencv Image Correctionim using OpenCV for Android. I would like to know,how to make image correction(auto adjustments of brightness/contrast) for image(bitmap) in android via Open…

vuex最简单、最详细的入门文档

如果你在使用 vue.js , 那么我想你可能会对 vue 组件之间的通信感到崩溃 。 我在使用基于 vue.js 2.0 的UI框架 ElementUI 开发网站的时候 , 就遇到了这种问题 : 一个页面有很多表单 , 我试图将表单写成一个单文件组件 , 但是表单 ( 子组件 ) 里的数据和页面 ( 父组件 ) 按钮交…

Vue生命周期详解 对应代码解析

-使用GitHub阅览 对于Vue的实例&#xff0c;比如 const app new Vue({...})浏览器解析到这段代码的时候&#xff0c;自动执行beforeCreate > created > beforeMount > mounted方法&#xff0c;每当data的某个属性值更改了&#xff0c;比如app.mes "hi"&…

所有其他指标均无用

对于队列&#xff0c;无论是实现为JMS &#xff0c;数据库表&#xff08;即Ruby的Delayed :: Job用于队列的什么&#xff09;&#xff0c;甚至是Amazon的SQS &#xff0c;用于评估队列状态的最常见指标是其长度。 从本质上讲&#xff0c;可以基于在任何给定时间队列中驻留多少消…