关于ThreadLocal,网络上的文章不计其数,一开始我也是无从下手,费了好大劲才搞懂,现在把自己理解的ThreadLocal记录在博客,以帮助到更多同学;
我理解的ThreadLocal
ThreadLocal中文名叫线程变量,它底层维护了一个map,key就是当前的ThreadLocal对象(可以理解为当前执行该段代码的线程),value就是你set的值,这个map保证了各个线程的数据互不干扰;
//这是ThreadLocal类的set方法源码 public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) //看这行,精华就在这行 map.set(this, value); else createMap(t, value); } //这是get方法 public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { //精华在这儿,用人话讲就是通过当前线程对象去map里面找对应的entry ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { //entry.value就拿到你set的value啦 T result = (T)e.value; return result; } } return setInitialValue(); }
ThreadLocal和Synchonized对比
Synchonized不用多说,不清楚的请移步synchronized底层实现原理
而ThreadLocal为解决并发编程提供了新的思路,synchronized是共享线程间的数据,而ThreadLocal是隔离线程间的数据
synchronized是利用锁的机制,使变量或代码块在某一时该只能被桶一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。
ThreadLocal使用不当引起的内存泄漏
ThreadLocal大法虽然好,但是使用不当后果很严重
造成原因:
ThreadLocal没有外部强引用,在发生垃圾回收的时候,ThreadLocal会被当成垃圾给干掉,而ThreadLocal对象又是Map中的key,map的key没了,那对应的entry永远不会被访问到,就无法被回收,进而造成内存泄漏
解决方案:
1、每次用完ThreadLocal都调用它的remove()方法清除数据
2、将ThreadLocal变量定义成private static,这样就一直存在ThreadLocal的强引用,也就能保证任何时候都能通过ThreadLocal的弱引用访问到Entry的value值,进而被清除
ok我话讲完