ThreadLocal线程局部变量

news/2024/7/7 19:02:48

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() {
			
			@Override
			public 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://lihuaxi.xjx100.cn/news/1556109.html

相关文章

基于Spring Boot+ Vue的健身房管理系统与实现

小熊学Java全能学面试指南&#xff1a;https://javaxiaobear.cn 摘要 随着健身行业的快速发展&#xff0c;健身房管理系统成为了提高管理效率和用户体验的重要工具。本论文旨在设计与实现一种基于前后端分离的健身房管理系统&#xff0c;通过前后端分离的架构模式&#xff0c;…

每日一题~二叉树的最近公共祖先

题目连接&#xff1a;236. 二叉树的最近公共祖先 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 思路分析&#xff1a; 由题可知&#xff0c;我们需要找到 p 和 q 两个二叉树的最近公共祖先节点&#xff0c;首先我们分析一下&#xff0c;这个最近公共祖先节点…

面试抱佛脚

App启动优化 (17条消息) Android 性能优化(一) —— 启动优化提升60%_凶残的程序员的博客-CSDN博客_android 启动优化 Android App优化之提升你的App启动速度之实例挑战 - 简书 Android性能优化--启动优化 - 简书 Android启动页优化&#xff0c;去黑屏实现秒启动 - 简书 (1…

3D动画制作和渲染需要什么样的硬件规格?

动画是艺术与技术的令人兴奋的融合&#xff0c;为无限的创造力提供了广阔的画布。为了将创意愿景变为现实&#xff0c;动画师需要适合其工艺的强大计算资源。每个动画项目都有不同的硬件需求&#xff0c;无论是制作简单的 2D 动画还是构建复杂的 3D 世界。因此&#xff0c;有抱…

如何在云服务器上成功安装MongoDB数据库并用Python连接(问题及解决方法)

最近购买了1台腾讯云轻量服务器做测试&#xff0c;想在上面安装MongoDB数据库。但安装过程并不顺利&#xff0c;遇到了几个问题。本文记录一下安装过程及遇到的问题和解决方法。 一、软件下载地址&#xff1a; 1.直接打开MongoDB官网&#xff1a;https://www.mongodb.com/ …

1688全店商品采集教程,1688店铺所有商品接口(详解1688店铺所有商品数据采集步骤方法和代码示例)

随着电商行业的快速发展&#xff0c;1688已成为国内的电商平台之一&#xff0c;拥有着海量的商品资源。对于一些需要大量商品数据的商家或者需求方来说&#xff0c;1688全店采集是非常必要的。本文将详细介绍1688全店采集的步骤和技巧&#xff0c;帮助大家更好地完成数据采集任…

leetcode100相同的树,C语言时间击败百分之百

最近“复习”到了二叉树&#xff0c;从leetcode找题做&#xff0c;发现相同的树 总之都是answer-coper 我就想先序迭代地dfs掉这道题&#xff0c;其他的答案上都有总结不赘述 下面主打我抄我自己 /*** Definition for a binary tree node.* struct TreeNode {* int val;*…

天视通等小众冷门摄像机接入安防监控系统EasyCVR平台的常见兼容问题及解决方法

众所周知&#xff0c;视频监控系统EasyCVR安防视频综合管理平台支持多类型设备、多协议方式接入&#xff0c;包括市场主流标准协议国标GB28181、RTMP、RTSP/Onvif协议等&#xff0c;以及厂家私有协议&#xff0c;如海康SDK、大华SDK、海康Ehome等。平台可兼容市面上绝大多数品牌…