ThreadLocal
说一下ThreadLocal
1、是什么?
ThreadLocal是java提供的线程本地存储的机制,可以利用该机制,将某个数据缓存在线程中,该线程可以在任意时刻,任意方法获取该值
2、底层?
ThreadLocal底层是通过ThreadLocalMap来实现的,每个Thread对象,都有一个ThreadLocalMap,Map 的key 存的是 ThreadLocal 对象,value 存的是需要缓存的数据。
3、存在的问题?
在线程池场景下使用ThreadLocal可能造成内存泄露,因为线程中有ThradLocalMap,即线程指向了ThreadLocalMap,ThreadLocalMap又指向了ThreadLocal对象,线程池中的线程对象是不会回收的,所以,ThreadLocalMap是不会回收的,该ThreadLocal也不会回收。该线程去执行任务二时,任务二会有新的ThreadLocal对象,对于任务二来说,任务一的ThreadLocal对象和value是没用的,但是仍然存在。久而久之,就可能造成内存泄露。
4、应用场景?
线程池下使用ThreadLocal注意:
我们需要在线程执行完后,手动的调用ThreadLocal 中的
remove()
线程中的 ThreadLocal对象
ThreadLocal的主要作用:
- 持有线程资源,供线程的各个部分使用
- 帮助维护多线程共享资源的一致性
- 线程安全的一种方案
ThreadLocal为什么要设计为static
private static ThreadLocal<String> connThreadLocal = new ThreadLocal<String>();
理由
为了避免重复创建TSO(thread specific object )即与线程相关的变量
需要注意的是:无法解决共享对象的问题
static 定义的类变量本来是可以进行变量共享的,但是ThreadLocal根除了对变量的共享
分析
一个ThreadLocal实例对应当前线程的一个TSO实例。因此,如果把ThreadLocal声明为某个类的实例变量,而不是静态变量,那么每创建一个该类的实例,就会导致一个新的TSO实例被创建,因此这个线程访问的时候,即便不会导致错误(同一个线程中创建了多个拥有ThreadLocal属性的对象,这个线程读取的时候可能读到不是相同的值),也会创建重复的对象。因此,一般我们将ThreadLocal定义为static的。
设计为static后,由于ThreadLocal是某一个类的静态变量。因此,只要相应的类没有被垃圾回收掉,那么这个类就会持有相应的ThreadLocal实例的引用。