ThreadLocal 的几点说明

简单定义和代码

ThreadLocal 提供线程本地变量。方式变量的线程安全问题。

猜测实现方式是使用map,保存线程中本地变量的内容,废话不多直接先上代码。

资源类,定义了一个ThreadLocal变量,初始化为0,。以及针对该变量的一些操作。

从运行结果可以看出来,三个线程,每个线程都会操作自己线程中的ThreadLocal,相互之间不干扰。

源码分析

本文大部分截图,以及概念都引用了这篇博客,有需要的小伙伴直接传送过去:https://www.cnblogs.com/fsmly/p/11020641.html

在ThreadLocal有一个内部类,ThreadLocalMap。而在线程中,存在如下的变量。

又上可知,每个线程的本地变量都存在都存在该县城 threadLocals 变量中,它的类型是 ThreadLocal中的内部类,ThreadLocalMap。如果当前线程一直不消亡,那么这些本地变量就会一直存在(所以可能会导致内存溢出),因此使用完毕需要将其remove掉。

ThreadLocal 中提供了对本地变量的相关操作

1、初始化,没什么好说的就是提供了初始化本地变量的方法。

2、get方法,ThreadLocalMap是否存在,存在返回其中本地变量,不存在创建一个。

3、set方法 

4、remove方法

5、ThreadLocalMap类似于一个hashMap的存在。是ThreadLocal的内部类,本文没有深入研究起源吗,有兴趣的小伙伴可以自行研究一下(只要是我懒,并且不想看)。

继承性和解决方案

ThreadLocal 是不支持继承性的,就是在父线程设置一个变量,子线程无法获取到这个变量。上代码:

从运行结果可以看出来,子线程获取threadLocal 是 null,而父线程中的是 Ok。如何解决该问呢,这时候就用到了ThreadLocal的子类 InheritableThreadLocal,修改后如下:

简单分析一下 InheritableThreadLocal。

从上图可知,InheritableThreadLocal 初始化的时候,操作的是线程中 inheritableThreadLocals变量,而不是之前的threadLocals变量。同时重写了 childValue 方法,在其父类ThreadLocal中,

是这样抛出一个异常的。

查看Thread 的init源码可知,父线程创建子线程的时候,会查看父线程的 InheritableThreadLocals是否存在,如果存在则在创建的时候把该变量赋给子线程的InheritableThreadLocals中。

使用注意事项

使用不当会导致内存泄露,因为ThreadLocalMap中的key是弱引用,所以GC回收的时候,可能导致key被回收,但是value(Entry)还存在,就是key消失了value还存在。

避免该方法的途径,是在使用住注意使用remove对变量进行回收。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: ThreadLocalJava 中的一个类,可以为每个线程绑定一个特定的变量,这样每个线程就可以访问自己绑定的变量了。使用时有一些注意点: 1. 不要将 ThreadLocal 的实例定义为 static 变量,因为这样会导致所有线程共享同一个变量,而不是每个线程都有自己的变量。 2. 在线程使用完 ThreadLocal 变量之后,一定要记得调用 remove() 方法清除线程的变量副本,因为如果不清除,线程池回收线程时,ThreadLocal 实例变量可能无法被回收,导致内存泄漏。 3. 在使用 ThreadLocal 的过程中,一定要注意线程安全问题。 4. 如果使用的是继承自 ThreadLocal 的匿名内部类,要注意内存泄漏的问题。 希望这些信息对你有帮助。 ### 回答2: ThreadLocal 是一个用于线程私有变量的类。它可以在多线程环境下确保每个线程都拥有独立的变量副本,避免了线程之间的数据共享和竞争。 使用 ThreadLocal 需要注意以下几点: 1. 避免内存泄漏:使用 ThreadLocal 时,要注意及时清理线程中的变量副本,避免长时间持有变量导致内存泄漏。 2. 初始值的设置:ThreadLocal 变量需要设置初始值,确保每个线程首次访问变量时能够获得正确的初始值。可以通过重写 ThreadLocal 的 initialValue() 方法来设置初始值。 3. 线程复用的问题:在线程池等线程复用的场景下,要注意 ThreadLocal 变量在线程复用时可能会引起数据污染的问题,需要在每次使用 ThreadLocal 变量之前,通过 remove() 方法将变量副本清除,保证线程复用时变量的独立性。 4. 变量的线程安全性:尽管 ThreadLocal 可以保证每个线程有独立的变量副本,但是,如果被存储在 ThreadLocal 中的变量本身不是线程安全的,仍然可能出现线程安全问题。因此,要注意保证存储在 ThreadLocal 中的变量的线程安全性。 5. 变量的传递问题:由于 ThreadLocal 变量只能在当前线程内共享,因此在不同线程之间传递数据需要通过其他方式,例如,可以利用线程池的 ThreadLocalMap 来实现传递。 总之,使用 ThreadLocal 时,要注意清理变量副本、设置初始值、处理线程复用、保证变量的线程安全性以及解决变量传递问题,以确保正常使用并避免潜在的问题。 ### 回答3: ThreadLocal 是一个 Java 中的线程局部变量,它提供了线程内的共享变量,在多线程环境下可以保证每个线程都拥有自己独立的变量副本,互不干扰。在使用 ThreadLocal 时需要注意以下几点: 1. 内存泄漏问题:使用 ThreadLocal 时需要小心内存泄漏问题。由于 ThreadLocal 中的变量是每个线程独立的,如果没有及时清理 ThreadLocal 对应的变量,可能会导致长时间不使用的线程仍然存在于内存中,造成内存泄漏。因此,在使用完 ThreadLocal 后应该显式地调用 remove() 方法清理对应的变量。 2. 初始化问题:ThreadLocal 变量的初始化是在每个线程中进行的,因此每个线程都会有一个对应的初始化值。在使用 ThreadLocal 时需要关注初始化值是否满足业务需求,否则可能会导致错误的结果。 3. 无法共享数据:虽然 ThreadLocal 在每个线程中都可以独立使用变量,但是无法实现线程间的数据共享。如果需要线程间的数据传递或共享,应该使用其他方式,如使用共享变量或传递参数等。 4. 线程重用问题:在线程重用的场景中,例如线程池,由于线程对象被复用,ThreadLocal 中的变量可能会被上一次使用的线程遗留下来,导致出现错误的结果。因此,在使用线程池等重用线程的情况下,需要特别小心 ThreadLocal 的使用。 总之,ThreadLocal 是一个非常有用的工具,能够解决线程间的变量共享问题。但是在使用时需要注意内存泄漏问题、初始化问题、无法共享数据和线程重用问题,以确保程序的正确性和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值