总述
ThreadLoca不是Thread,是一个线程内部的数据存储类。它可以在指定的线程中存储数据,并且只有在此线程中才可以获取到存储到数据,其他线程是无法获取到的。(提供了线程独有的变量)
demo
public class ThreadLocalTest {
public static void main(String[] args) {
final ThreadLocal<String> threadLocal1 = new ThreadLocal<>();
final ThreadLocal<Integer> threadLocal2 = new ThreadLocal<>();
new Thread(new Runnable() {
@Override
public void run() {
threadLocal1.set("A");
threadLocal2.set(1);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
System.out.println(threadLocal1.get());
System.out.println(threadLocal2.get());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
threadLocal1.set("B");
threadLocal2.set(2);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
System.out.println(threadLocal1.get());
System.out.println(threadLocal2.get());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
System.out.println(threadLocal1.get());
System.out.println(threadLocal2.get());
}
}).start();
}
}
结果如下:
Thread-2
null
null
Thread-1
B
2
Thread-0
A
1
可以看出,虽然在不同线程中访问的是同一个ThreadLocal对象,但是它们通过ThreadLocal来获取到的值却是不一样的,这就是ThreadLocal的奇妙之处。
内部实现
ThreadLocal<T>使用的是泛型。
ThreadLocalMap就是用来存储的内部类。其内部是一个Entry[] table数组,存储所有数据,Entry对象的key为ThreadLocal,value为其对应的值。数组默认大小是16。
当ThreadLocal使用set方法时,会先获取当前线程,然后调用getMap(currentThread),获取线程中的数据存储类ThreadLocalMap。如果ThreadLocalMap不为空,就调用set方法进行赋值。如果为空,就进行初始化,并将数据设置
这样,每一个Thread中,都保留着自己的一份ThreadLocalMap数据存储类,数据独享。
使用get方法时,会先获取当前线程,然后调用getMap(currentThread),获取线程中的数据存储类ThreadLocalMap,再进行取值
在线程消失之后,其线程局部实例的所有副本都会被垃圾回收(除非存在对这些副本的其他引用)
内存泄漏
key为弱引用。弱引用一定程度上回收了无用对象,但前提是开发者手动清理掉ThreadLocal对象的强引用。
回收之后成了(null, value)
只要线程一直不死,ThreadLocalMap的key-value一直在涨
如果线程执行完之后销毁,value也会被回收,这样也没问题。但如果是在线程池中,线程执行完后不被回收,而是返回线程池中,Thread有个强引用指向ThreadLocalMap,ThreadLocalMap有强引用指向Entry,导致value无法被回收,一直存在内存中。在执行了ThreadLocal.set()方法之后一定要记得使用ThreadLocal.remove(),将不要的数据移除掉,避免内存泄漏。
原文链接:https://blog.csdn.net/wy1404081737/article/details/81489080

1091

被折叠的 条评论
为什么被折叠?



