1.首先看了 Java并发编程:深入剖析ThreadLocal 这篇文章,这篇文章首先用用一个数据库连接的例子,如多个线程同时进行连接和关闭数据库操作,有可能会导致某个线程刚打开的数据库连接操作,被另一个线程打开的数据库关闭操作给关闭了。然后往下再看没看明白。
2.接着看了ThreadLocal工作原理这篇文章
这篇文章看完了了解了个大概意思:ThreadLocal 定义了多个Threadlocal这样的线程共享局部变量,解决办法就是有一个ThreadLocalMap这样的Map,Map的key是ThreadLocal这个变量,value是变量副本值,这样说可能还不知道是啥意思,看一个例子。
/**
* 三个ThreadLocal
*/
private static ThreadLocal<String> threadLocal1 = new ThreadLocal<>();
private static ThreadLocal<String> threadLocal2 = new ThreadLocal<>();
private static ThreadLocal<String> threadLocal3 = new ThreadLocal<>();
//线程池变量指定一个线程
ExecutorService executorService = Executors.newFixedThreadPool(1);
executorService.execute(() -> {
threadLocal1.set("123");
threadLocal2.set("234");
threadLocal3.set("345");
Thread t = Thread.currentThread();
System.out.println(Thread.currentThread().getName());
});
如在这个例子中,ThreadLocalMap中的key就是 threadLocal1,threadlocal2,threadlocal3,对应的value就是“123”,‘234’,‘345’
3.接着看了第三篇文章 Java多线程编程-(8)-多图深入分析ThreadLocal原理 感觉最后看的这篇文章,真是学到了好多,我也不清楚是不是前两篇进行了铺垫,还是第三篇讲的好的原因,反正看第三篇的感觉讲的很通透,脑子里终于大概知道了ThreadLocal是个什么东东。
这里放一张图:
分列左右的Thread分别代表一个线程,是不同的线程,每个线程Thread中有唯一的一个ThreadLocalMap,其中ThreadLocalMap中的Entry存储了一个键值对,就是在上面的第2部分说的键值对。
set()方法原理:线程中的ThreadLocalMap变量的值是在ThreadLocal对象进行set或者get操作时创建的,创建后,对于加入的每个键值对都是通过类似于HashMap的方式进行添加元素,也就是先计算添加的ThreadLocal对象的hashcode值,找到下标,找到对应的Entry,设置对应的Entry的key和value值;
get()方法原理:使用get()f方法获取,计算当前threadlocal1变量的hashcode值,然后找到对应的entry[i]处,比较key是否相同,相同则返回当前value。
ThreadLocal为什么会出现OOM,出现的深层次原理
定义ThreadLocal这个类后,在每个Thread中有ThreadLocalMap这个Map,ThreadLocalMap中的key是ThreadLocal对象,value是共享的变量副本值,
由于ThreadLocal是弱引用,每次GC都会清除掉,那么key清除掉,留下了value无法访问到,造成内存泄漏。这种情况在下次使用set,get方法就可以清除掉value的值,或者调用remove方法。在ThreadLocal的get(),set(),remove()的时候都会清除线程ThreadLocalMap里所有key为null的value