Java中的线程ThreadLocal详细解析

 更新时间:2023年10月26日 09:04:32   作者:buzhbuzh  
这篇文章主要介绍了Java中的线程ThreadLocal详细解析,ThreadLocal是线程本地变量,存储在ThreadLocal里面的数据都是线程安全的,一般ThreadLocal适用的场景多是各个线程间没有变量共享需要的同步问题场景,需要的朋友可以参考下

一 Java中的引用关系

Java中的引用分为了强引用、弱引用、软引用、虚引用

  • 强引用: 垃圾回收的时候,如果内存不足也不会进行垃圾回收,会报out-of-memory异常
  • 弱引用: 垃圾回收的时候,如果内存不够,则数据被回收.
  • 软引用: 垃圾回收的时候,软引用会立刻进行回收
  • 虚引用: 垃圾回收的时候,软引用会立刻进行回收

二 ThreadLocal代码实现

ThreadLocal是线程本地变量,存储在ThreadLocal里面的数据都是 线程安全的.

一般ThreadLocal适用的场景多是各个线程间没有变量共享需要的同步问题场景,比如一个简单的SimpleDateFormat类,该类不是线程安全的,却是有状态的,如果将SimpleDateFormat设置为静态的,所有线程共享,那么就会出现线程安全的问题,其中一个线程修改日期格式为“yyyyMMdd”,然后可能会影响到另外一个需要格式为“yyyy-MM-dd”的线程。但是如果在方法中每次用到的时候都new一个SimpleDateFormat类又太费内存(SimpleDateFormat这种简单的类倒还好,若是一些比较占用资源的比如数据库连接类等,就会让加大整个数据库的压力),这时候采用ThreadLocal为每一个线程保存一份SimpleDateFormat副本,这样既不会说每次调用方法都会生成一个对象,也不会在并发时产生线程同步问题。这就像是在共享一个静态变量和每次使用都new一个对象两者之间的一种折中处理方法。

自己实现的ThreadLocal

在这里插入图片描述

通过一个全局map, key是Thread对象,value是对应存储的数据,这种情况下 如果map不销毁,对应的Thread线程就不发被回收,导致内存泄露

JDK中使用的ThreadLocal

在这里插入图片描述

JDK8中在Thread对象中引用ThreadLocalMap,ThreadLocalMap的生命周期是Thread是同一个生命周期.

ThreadLocalMap的实现

(1) Entry数组实现

在这里插入图片描述

Entry数组是线程中实际存放数据的地方,key是ThreadLocal,是一个弱引用,value是对应存储的值.

为什么ThreadLocalMap#key是一个弱引用

如果外部不使用了ThreadLocal,则对应的数据不应该存储在ThreadLocal中,应该被删除掉,防止内存泄漏

ThreadLocalMap的属性

        private static final int INITIAL_CAPACITY = 16;
    	//存储数据的地方
        private Entry[] table; //
    	//数量
        private int size = 0;
        private int threshold; // Default to 0

ThreadLocal的方法

ThreadLocal#set()方法

在这里插数据入图片描述

(1) 第一步 获取到当前线程的ThreadLocalMap

(2) 第二步 初始化ThreadLocalMap

(3) 第三步 将ThreadLocal作为key,value值作为值,设置到map中

ThreadLocal # get()方法

在这里插入图片描述

方法主要完成两个功能: (1) 完成数据的读取 (2) 将ThreadLocalMap中key为NULL的数据从ThreadLocalMap中删除

ThreadLocalMap中的entry其实是继承的弱引用,如果该弱引用指向的ThreadLocal没有在外部被强引用指向的话,在下次gc的时候就会被回收,那这样的话就会出现ThreadLocalMap中存在key为null的情况,这样的数据对于map来讲是脏数据,这样的脏数据没有用,却一直占用着map的存储空间,这其实就是一种内存泄漏,所以需要来释放掉这些空间

三 ThreadLocalMap的内存泄漏问题

如果ThreadLocal无强引用进行应用,则在垃圾回收的时候会把这个key进行回收.

这个时候,因为线程还存活,所以ThreadLocalMap依旧存在,但是key为null,这个 key对应的value就无法被访问到了,造成内存泄漏.

JDK团队自己的解决办法

调用get()、set()方法的时候,自动清理掉ThreadLocalMap中key为null的数据

开发者的解决办法 使用ThreadLocal后,调用ThreadLocal

到此这篇关于Java中的线程ThreadLocal详细解析的文章就介绍到这了,更多相关Java的ThreadLocal内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java实现九宫格拼图游戏

    java实现九宫格拼图游戏

    这篇文章主要为大家详细介绍了java实现九宫格拼图游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • Java Executor 框架的实例详解

    Java Executor 框架的实例详解

    这篇文章主要介绍了Java Executor 框架的实例详解的相关资料,这里提供实例来帮助大家学习理解这部分内容,需要的朋友可以参考下
    2017-09-09
  • SpringBoot MainApplication类文件的位置详解

    SpringBoot MainApplication类文件的位置详解

    这篇文章主要介绍了SpringBoot MainApplication类文件的位置详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Java 数据结构进阶二叉树题集上

    Java 数据结构进阶二叉树题集上

    二叉树可以简单理解为对于一个节点来说,最多拥有一个上级节点,同时最多具备左右两个下级节点的数据结构。本文将带你通过实际题目来熟练掌握
    2022-04-04
  • 为何Java8需要引入新的日期与时间库

    为何Java8需要引入新的日期与时间库

    这篇文章主要给大家介绍了关于Java8为什么需要引入新的日期与时间库的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • EntityWrapper如何在and条件中嵌套or语句

    EntityWrapper如何在and条件中嵌套or语句

    这篇文章主要介绍了EntityWrapper如何在and条件中嵌套or语句,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • SSM框架整合之Spring+SpringMVC+MyBatis实践步骤

    SSM框架整合之Spring+SpringMVC+MyBatis实践步骤

    大家都知道Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,本文主要介绍三大框架的整合包含spring和mybatis的配置文件,还有spring-mvc的配置文件的详细介绍,通过项目实践步骤给大家详细介绍,感兴趣的朋友一起看看吧
    2021-06-06
  • java封装空值建议使用Optional替代null的方法示例解析

    java封装空值建议使用Optional替代null的方法示例解析

    这篇文章主要为大家介绍了java封装空值建议使用Optional替代null的方法原理解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • knife4j3.0.3整合gateway和注册中心的详细过程

    knife4j3.0.3整合gateway和注册中心的详细过程

    这篇文章主要介绍了knife4j3.0.3整合gateway和注册中心的详细过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03
  • Java中设置session超时(失效)的三种方法

    Java中设置session超时(失效)的三种方法

    这篇文章主要介绍了Java中设置session超时(失效)的三种方法,本文讲解了在web容器中设置、在工程的web.xml中设置、通过java代码设置3种方法,需要的朋友可以参考下
    2015-07-07

最新评论