对于ThreadLocal的理解
- 什么是ThreadLocal
- ThreadLocal的使用场景
- 1.线程隔离
- 2.跨函数传值
- 正确使用
- 感想
什么是ThreadLocal
在Java的多线程并发执行的过程中,为了保证多个线程对变量的安全访问,可以将变量放到ThreadLocal类型的对象中,是变量在每一个线程中都有独立的值,不会出现一个线程读取变量时被另一个线程修改的现象。ThreadLocal类通常被翻译为本地变量类或者线程局部变量。
ThreadLocal位于JDK的java.lang核心包中。如果程序创建了一个ThreadLocal实例,那么在访问这个变量的值时,每个线程都会拥有一个独立的、自己的本地值。“线程本地变量”可以看成专属于线程的变量,不受其他线程干扰,保存着线程的专属数据。当线程结束后,每个线程所拥有的那个本地值会被释放。在多线程并发操作“线程本地变量”的时候,线程各自操作的是自己的本地值,从而规避了线程安全问题。
ThreadLocal本质上相当于Map<key,value>,同时threadLocal可以很好的额解决线程安全的问题,它通过为每一个线程提供一个独立的本地值去解决并发冲突问题。在很多情况下,使用ThreadLocal比直接使用同步锁解决问题更加方便,且程序拥有更高的并发性。
public class ThreadLocalTest02 {
public static void main(String[] args) {
ThreadLocal<String> local = new ThreadLocal<>();
IntStream.range(0, 10).forEach(i -> new Thread(() -> {
local.set(Thread.currentThread().getName() + ":" + i);
System.out.println("线程:" + Thread.currentThread().getName() + ",local:" + local.get());
}).start());
}
}
输出结果:
线程:Thread-0,local:Thread-0:0
线程:Thread-1,local:Thread-1:1
线程:Thread-2,local:Thread-2:2
线程:Thread-3,local:Thread-3:3
线程:Thread-4,local:Thread-4:4
线程:Thread-5,local:Thread-5:5
线程:Thread-6,local:Thread-6:6
线程:Thread-7,local:Thread-7:7
线程:Thread-8,local:Thread-8:8
线程:Thread-9,local:Thread-9:9
ThreadLocal的使用场景
1.线程隔离
ThreadLocal主要的价值在于线程隔离,ThreadLocal中的数据只属于当前线程,其本地值对别的线程是不可见的,在多下线程环境下可以防止自己的变量被其他线程篡改。另外由于每个线程之间相互隔离,避免了同步加锁带来的性能影响。
T和read在线程隔离常用的案例为:可以为每一个线程保存一个会话信息、数据库连接、Http请求,这样一个线程所有调用到的处理函数都可以非常方便的访问这些资源。最常见的就是使用ThreadLocal实现数据库连接独享、Session数据管理等
2.跨函数传值
通常用于同一个线程中,在跨类,方法去传递数据时,如果不使用ThreadLoccal,那么相互之间的数据传递就必须依靠返回值和参数,这样就无形之中增加了这些类或者方法之间的耦合度。由于ThreadLocal的特性,同一线程在某些地方进行设置,在该线程任何地方放都可获取到。线程执行过程中所所执行的函数都可以读写ThreadLocal变量的本地治,从而实现跨函数的值传递。
这点就很让人容易联想到越权的问题,在使用security框架时,这个问题很好解决,我们可以从 SecurityContextHolder中得到登录用户的所有信息,但是如果没有使用 Security框架呢,那么ThreadLocal或许就是一个很好的解决办法。
.
正确使用
ThreadLocal内部的ThreadLocalMap的key使用的时弱引用指向ThreadLocal的实例对象,当该实例对象被回收的时候,如果ThreadLocalMap的key使用的也是强引用指向ThreadLocal那么该实例就不会被回收,也就会造成内存泄漏的问题。
同时使用弱引用也会出现类似问题,当ThreadLocal实例被回收时,弱引用也被回收时,key值为null,但是value值不为null这也会造成内存泄漏,但是这个问题我们可以通过调用ThreadLocal的remove方法解决。
感想
juc是真的难,太痛苦了,本来以为jvm就够难了,但是当我打开juc的书翻开第二页,我就知道我错了,每个字都会读,合到一起就看不懂了,希望多看几遍能够理解吧。阿弥陀佛!