谈谈对ThreadLocal的理解
ThreadLocal的数据结构是:
在Thread线程对象内部定义了一个ThreadLocalMap,通过ThreadLocal对象访问,访问时key是当前ThreadLocal对象,value保存当前线程想要保存的数据
ThreadLocalMap的数据结构:
哈希表,当产生哈希冲突时,采用“开放地址法”处理,就是当前下标发生哈希冲突时,会将当前下标作为0,向后重新计算下标
ThreadLocal的作用:
在当前线程范围内保存数据,可以在同一个线程执行期间,在不同的类和方法之间共享数据的场景
展示一个小案例说明在不同类中还是可以访问线程的ThreadLocal所保存的值
package Threadday5;
public class Test03 {
public static final ThreadLocal<String> threadlocal = new ThreadLocal<String>();
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
//向threadlocal中存放当前线程想要保存的数据
threadlocal.set("吕布");
decth();
//不同类的方法
new nb().show();
}
},"线程1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
threadlocal.set("貂蝉");
decth();
new nb().show();
}
},"线程2");
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
public static void decth() {
//获取当前线程中所保存的数据
System.out.println("Test03"+Thread.currentThread().getName()+":"+threadlocal.get());
}
}
class nb {
public static void show() {
System.out.println("nb"+Thread.currentThread().getName()+":"+Test03.threadlocal.get());
}
}
当在父子线程中,想要达到ThreadLocal数据的共享,就要使用InheritableThreadLocal保存数据
package Threadday5;
public class Test04 {
//父子线程,使用InheritableThreadLocal保存数据
public static final InheritableThreadLocal<String> threadlocal = new InheritableThreadLocal<String>();
public static void main(String[] args) throws InterruptedException {
//在main主线程中保存数据
threadlocal.set("我本将心向明月");
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
threadlocal.get();
System.out.println(Thread.currentThread().getName()+":"+threadlocal.get());
}
});
thread.start();
thread.join();
System.out.println("over~");
}
}
如何避免内存泄漏?
使用ThreadLocal做为ThreadLocalMap中的key,会避免内存泄漏,并且key被设计为WeakReference弱引用,可以及时被GC(垃圾回收机制)回收,避免内存泄漏。
引用关系:
- 强引用:发生GC(垃圾回收),都不会回收
- SoftReference软引用:内存不足时,发生GC(垃圾回收),会被回收
- WeakReference弱引用:发生GC(垃圾回收),就会被回收
- 虚引用:基本不存在