1 ThreadLocal简单介绍:
ThreadLocal是线程级变量,针对于当前线程的变量,可以在ThreadLocal中存储相关数据,仅限当前的线程链可以使用,对其他的线程是隔离的!
2 ThreadLocal的本质:
(1) 首先需要知道每个Thred都维护着一个ThreadLocalMap;
(2) ThreadLocalMap是ThreadLocal的内部静态类
(3) 查看ThreadLocal的Get/Set方法
Set:
Get:
总结: ThreadLocal就是在操作Thread维护的ThreadLocalMap,将ThreadLocal本身作为map的key, 我们需要在当前线程中贡献的数据作为value存入map中,在当前线程中只要保证ThreadLocal对象不变,就可以从ThreadLocalMap中取到我们需要线程级别共享的数据;
3 Thread使用注意存在的问题:
(1)内存泄漏
ThreadLocal是将自己的对象存入ThreadLocalMap中作为key,但是ThreadLocalMap中的Entry是继承的java.lang.ref.WeakReference,这个过程是个弱引用,其实就是这个key在第一伦的gc中key会被清理,但是value是强引用,然后造成键值对成(null,value),从而只要当前的线程不结束,空键的数据会累积,占用内存,造成内存泄漏,一般在写代码时候都是线程池的方式提交线程任务,很有可能使用ThreadLocal造成内存泄漏
(2) 预防内存泄漏
在线程共享数据结束后Thread通过Local的remove()清理;
4 ThreadLocal使用场景:
(1) session共享,拦截器/过滤器将当前用户的信息装入ThreadLocal进行本线程数据共享
(2) 仅仅在本线程中有效的数据
5 使用小demo:
public class ThreadLocalTest {
public static void main(String[] args) {
Thread thread = Thread.currentThread();
DataPool.pool.set("欢迎大家指导我这努力学飞的小菜鸟,......");
new AService().getPoolData();
new BService().getPoolData();
}
}
class AService{
public void getPoolData(){
System.out.println(DataPool.pool.get());
}
}
class BService{
public void getPoolData(){
System.out.println(DataPool.pool.get());
}
}
class DataPool {
static final ThreadLocal<Object> pool = new ThreadLocal<Object>() {
@Override
protected Object initialValue() {
//指定初始化的数据
return 0;
}
};
static {
//查看一下数据
System.out.println("数据为:" + pool.get());
}
/**
* 思维扩展:在不考虑多线程影响数据的情况下.我们可以使用map尝试搭建共享数据载体
*/
}