普通的共享变量在对各线程访问的状态下是不安全的,考虑使用加锁的手段或者其他手段
而Thread Local可以实现共享变量的县城内共享,让每个线程各用各的资源对象,避免引发线程安全问题
局部变量能不能实现呢?答:不能,局部变量不能跨越方法使用
换而言之,就是TreadLocal实现了线程内的资源共享
那TreadLocal怎么实现线程隔离的呢
其原理就是
每个线程内有一个ThreadLocalMap(基础长度为15,满10 扩容)类型的成员变量,来储存资源对象
而这个TreadLocalMap解决hash冲突使用的是开放寻值法(就是如果hash冲突就找到下一个空闲的位置存放)
1.调用set方法,就是以ThreadLocal对象作为自己的key,资源对象作为value,放入当前线程的TreadLocalMap集合中(当前的方法的参数就是这个value的值);
2.调用get方法,就是以TreadLocal作为自己的key,到当前线程中查找关联的资源值;
3.调用remove方法,就是以TreadLocal作为字节的key,一处当前线程的关联资源值;
总结:ThreadLocal起到的作用就是关联资源对象,在线程中起到隔离作用的是ThreadLocalMap集合
TreadLocalMap的Key设计的是弱引用储存,即使忘记手动释放资源最终也有机会被JVM的垃圾回收机制给回收掉,但是GC只能让key回收掉,之后需要根据key是否为null来判断是否释放value
当调用方法时会对内存中的key、value进行检查
TreadLocalMap的key的释放时机
获取key发现null key
set key,会扫描请出临近的null key,发动次数与元素个数,是否发现null key有关
remove时,一般使用TreadLocal时都把它作为静态变量,因此GC无法回收
TreadLocalMap的value的释放时机
get key为null时回收value并存储一个key
set key为null时回收value,并且会回收临近的nullkey和null值
remove,主动清理,不主动清理的话可能出现内存泄露