1. 是什么


是一个数据结构,有点像HashMap,可以保存"key : value"键值对,但是一个ThreadLocal只能保存一个,并且各个线程的数据互不干扰。


作用:在多线程环境下,如何防止自己的变量被其它线程篡改


2. 如何实现线程隔离



  • 每个线程中维护一个ThreadLocalMap数据结构,当执行set方法时,其值是保存在当前线程的threadLocals变量中,当执行get方法中,是从当前线程的threadLocals(ThreadLocal.ThreadLocalMap类)变量获取。
  • 所以在线程1中set的值,对线程2来说是接触不到的,而在线程2中重新set的话,也不会影响到线程1中的值,保证了线程之间不会互相干扰。


3. ThreadLocalMap


类HashMap的数据结构,但是并没有实现Map的接口。


在ThreadLocalMap中,也是初始化一个大小为16的Entry数组,Entry对象用来保存每一个key-value键值对,只不过这里的key永远都是ThreadLocal对象。Entry中不存在链表。


hash冲突?找下一个空位置


Java基础回顾:ThreadLocal_内存泄漏


4. 为什么会导致内存泄漏,如何避免?


当使用ThreadLocal保存一个value时,会在ThreadLocalMap中的数组插入一个Entry对象,在ThreadLocalMap的实现中,Entry的key是ThreadLocal对象的弱引用。ThreadLocal在没有外部强引用时,发生GC时会被回收,如果创建ThreadLocal的线程一直持续运行,那么这个Entry对象中的value就有可能一直得不到回收,发生内存泄漏。


如何避免:1. 显示的调用remove方法


 


注:内存泄漏:内存申请后,用完没有释放,造成可用内存越来越少,即无法释放已申请的内存。


 


5. 主要应用场景


数据库管理类


session管理



// 阿里巴巴 java 开发手册中推荐的 ThreadLocal 的用法:
import java.text.DateFormat;
import java.text.SimpleDateFormat;

public class DateUtils {
public static final ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>(){
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};
}
// 然后我们再要用到 DateFormat 对象的地方,这样调用
// DateUtils.df.get().format(new Date());


 


多线程测试


Java基础回顾:ThreadLocal_数组_02


 


一点浩然气,千里快哉风!