ThreadLocal线程局部变量

1.原理

        ThreadLocal是用来保存当前线程数据的,每一个线程的内部都有一个ThreadLocalMap,当前这个map中存储了以当前ThreadLocal,具体的数据的一个个Entry对象。

                

        为什么非得以ThreadLocal对象作键呢?因为一个线程可能使用了不止一个ThreadLocal对象,如果以当前线程对象做键,再去找对应的ThreadLocal就很麻烦,产生混淆。

        由于每一个线程都有属于自己的ThreadLocal线程局部变量,所以很好的实现了线程之间的数据隔离ThreadLocal中保存的数据仅属于当前线程)。       

2.ThreadLocal中的常见方法:

        (1)存储数据        set()

        (2)获取数据        get()

        (3)清除数据         remove()

        那么问题来了,具体是怎样利用ThreadLocalMap查找数据的呢?不论是set()、get()、remove()等方法对当前map进行操作时,最终都定位到了通过计算出的下标来操作。

        而这个下标是通过哈希算法计算得到的,操作ThreadLocalMap是以当前的ThreadLocal作key,通过当前的key的HashCode值和Entry[]数组长度-1“&”运算,来计算出实际操作位置的下标,从而达到访问元素的目的。        

        作按位与运算的效果和利用哈希值直接进行取余%运算一样,但效率大大提高

3.如何实现父子线程共享数据?

        利用了jdk提供ThreadLocal的子类InheritableThreadLocal来实现。

public class ThreadLocalTest {public static void main(String[] args) {InheritableThreadLocal<String> threadLocal = new InheritableThreadLocal<String>();threadLocal.set("风萧萧兮易水寒");System.out.println("main主线程:"+threadLocal.get());Thread thread = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("子线程:"+threadLocal.get());}});thread.start();}
}

        main函数为父线程,创建了一个thread子线程,利用InheritableThreadLocal这个子类来共享父线程的数据。

        父线程子线程均输出“风萧萧兮易水寒”。

4.ThreadLocal如何避免内存泄露

        执行完相关的业务逻辑后,最终在finally代码块中都会调用remove()方法,将当前map中的ThreadLocal键置为空,value置为空,从而在垃圾回收的时候及时回收无用数据。

5.应用

        (1) 线程的数据隔离

        因为ThreadLocal对象只属于当前线程,那么ThreadLocal中的数据也属于当前线程,在多线程并发的情况下,很好的实现了不同线程的数据隔离,避免了采用synchronized锁机制来保证线程安全而导致的性能上的代价。

        例如:SqlSession会话对象绑定,避免多个线程使用同一个SqlSession对象,由于关闭导致异常。

//当前线程的线程局部变量
private static final ThreadLocal threadSession= new ThreadLocal();public static SqlSession getSession(){//获取session会话方法SqlSession s = (SqlSession)threadSession.get();//通过仅属于当前线程的threadSession对象来获取if(s==null){//为空s = getSqlSessionFactory().openSqlSession();//则重新建立会话threadSession.set(s);//并存到ThreadLocalMap中去}
}

        (2)跨函数调用

        数据通常用于同一个类中的传递,如果利用方法传递势必要关心方法的返回值类型及参数,但利用ThreadLocal可以直接实现获取,这样做还达到了解耦的效果。

        例如:RequestContextHolder源码就有很好的体现

@Nullable  
public static RequestAttributes getRequestAttributes() {// 获取当前线程中的存储的Request Attribute//直接通过ThreadLocal对象来获取RequestAttributes attributes = requestAttributesHolder.get();  if (attributes == null) {  attributes = inheritableRequestAttributesHolder.get();  }  return attributes;  
}private static final ThreadLocal<RequestAttributes> requestAttributesHolder =  new NamedThreadLocal<>("Request attributes");  private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder =  new NamedInheritableThreadLocal<>("Request context");

以上就是我对ThreadLocal线程区域对象的粗略理解,欢迎诸君共同探讨。

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

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

相关文章

若依前端使用

初始化页面时&#xff0c;路由上加参数 多个菜单对应一个页面&#xff0c;默认查询的数据状态不一样 vue 页面上 通过 debugger; 查看所有的参数&#xff0c; 最后取到了

网络基础(一)

网络基础&#xff08;一&#xff09; 在本篇文章中&#xff0c;我会详细介绍网络的一些基础知识&#xff0c;之后也会有持续的更新来帮助大家学习网络&#xff0c;希望大家可以通过博客学到更多的知识&#xff01; 了解网络 去百度查询可以知道&#xff0c;网络是由若干节点和…

Unity SteamVR 开发教程:用摇杆/触摸板控制人物持续移动(2.x 以上版本)

文章目录 &#x1f4d5;教程说明&#x1f4d5;场景搭建&#x1f4d5;创建移动的动作&#x1f4d5;移动脚本⭐移动⭐实时调整 CharacterController 的高度 &#x1f4d5;取消手部和 CharacterController 的碰撞 持续移动是 VR 开发中的一个常用功能。一般是用户推动手柄摇杆&…

Netty2

文章目录 Netty2Netty入站与出站机制Netty的handler链的调用机制 Netty2 Netty入站与出站机制 基本说明&#xff1a; 1&#xff09;netty的组件设计&#xff1a;Netty的主要组件有Channel&#xff0c;EventLoop&#xff0c;ChannelFuture&#xff0c;ChannelHandler&#xff…

SaaS架构C/S检验科LIS系统源码: 检验申请、标本编号、联机采集

适用于医院检验科实际需要的LIS管理系统, 实现检验业务全流程的计算机管理。从检验申请、标本编号、联机采集、中文报告单的生成与打印、质控图的绘制和数据的检索与备份。通过将所有仪器自身提供的端口与科室LIS系统中的工作站点连接,实现与医院HIS系统的对接。 通过门诊医生和…

如何使用ArcGIS中的Arcmap进行矢量和栅格数据裁剪?

在地理信息系统(GIS)中&#xff0c;我们经常需要处理各种空间数据&#xff0c;而矢量和栅格数据是最常见的两种数据类型。有时候&#xff0c;我们需要对数据进行裁剪&#xff0c;以提取出我们需要的特定区域的数据。本文将介绍如何使用ArcGIS中的Arcmap软件对矢量和栅格数据进行…

选择渲染农场的几个标准

随着电影、电视剧等影视作品的制作越来越依赖于计算机特效&#xff0c;渲染农场的使用也变得越来越普遍。渲染农场是一种利用大量计算机图形处理器&#xff08;GPU&#xff09;来加速渲染过程的服务。在选择渲染农场时&#xff0c;有几个标准可以帮助您确定哪个农场是适合您的项…

Unity3D C# 反射与特性的配合使用

需求分析 情况&#xff1a; 假如我们是一个动物园的管理员&#xff0c;我们需要统计园内的所有动物和动物的行为。 举例&#xff1a; 现在园区内有猫、狗和鸡。猫对应的行为是喵喵喵和卖萌&#xff0c;狗对应狗吠和干饭&#xff0c;鸡对应篮球和打鸣那么这时候我要统计这些&a…

在qml中将一个16进制表示的颜色加上透明度

在qml中&#xff0c;我们在指定控件的颜色时&#xff0c;可以直接通过16进制的字符串来表示&#xff0c;比如"#ff0000"; 这种方式也比较符合UI设计人员的使用习惯。 但是假如要在此颜色的基础上&#xff0c;加个透明度的话&#xff0c;就要重新计算一番&#xff0c;比…

腾讯云2核4G服务器5M带宽 218元一年 优惠价格明细表

腾讯云2核4G服务器5M带宽可以选择轻量应用服务器或云服务器ECS&#xff0c;轻量2核4G5M带宽服务器218元一年&#xff1a; 腾讯云2核4G服务器5M带宽收费 腾讯云2核4G服务器可以选择轻量应用服务器或者ECS云服务器&#xff0c;云服务器ECS是专业级云服务器&#xff0c;大多数使用…

deepin V23通过flathub安装steam畅玩游戏

deepin V23缺少32位库&#xff0c;在星火商店安装的steam,打开报错&#xff0c;无法使用&#xff01; 通过flathub网站安装steam,可以正常使用&#xff0c;详细教程如下&#xff1a; flathub网址&#xff1a;主页 | Flathub 注意&#xff1a;flathub下载速度慢&#xff0c;只…

小程序自定义tabbar

前言 使用小程序默认的tabbar可以满足常规开发&#xff0c;但是满足不了个性化需求&#xff0c;如果想个性化开发就需要用到自定义tabbar,以下图为例子 一、在app.json配置 先按照以往默认的形式配置&#xff0c;如果中间的样式特殊则不需要配置 "tabBar": {&qu…