浅谈threadlocal
作者:互联网
1.什么是threadlocal?
ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。
2.应用场景? 1、在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。 2、线程间数据隔离 3、进行事务操作,用于存储线程事务信息。 4、数据库连接,Session会话管理。 3.源码解析(set,get,romeve三个方法)1、set方法源码
1 public void set(T value) { 2 //(1)获取当前线程(调用者线程) 3 Thread t = Thread.currentThread(); 4 //(2)以当前线程作为key值,去查找对应的线程变量,找到对应的map 5 ThreadLocalMap map = getMap(t); 6 //(3)如果map不为null,就直接添加本地变量,key为当前定义的ThreadLocal变量的this引用,值为添加的本地变量值 7 if (map != null) 8 map.set(this, value); 9 //(4)如果map为null,说明首次添加,需要首先创建出对应的map 10 else 11 createMap(t, value); 12 }
在上面的代码中,(2)处调用getMap方法获得当前线程对应的threadLocals(参照上面的图示和文字说明),该方法代码如下
ThreadLocalMap getMap(Thread t) { return t.threadLocals; //获取线程自己的变量threadLocals,并绑定到当前调用线程的成员变量threadLocals上 }
如果调用getMap方法返回值不为null,就直接将value值设置到threadLocals中(key为当前线程引用,值为本地变量);如果getMap方法返回null说明是第一次调用set方法(前面说到过,threadLocals默认值为null,只有调用set方法的时候才会创建map),这个时候就需要调用createMap方法创建threadLocals,该方法如下所示
1 void createMap(Thread t, T firstValue) { 2 t.threadLocals = new ThreadLocalMap(this, firstValue); 3 }
createMap方法不仅创建了threadLocals,同时也将要添加的本地变量值添加到了threadLocals中。
2、get方法源码
在get方法的实现中,首先获取当前调用者线程,如果当前线程的threadLocals不为null,就直接返回当前线程绑定的本地变量值,否则执行setInitialValue方法初始化threadLocals变量。在setInitialValue方法中,类似于set方法的实现,都是判断当前线程的threadLocals变量是否为null,是则添加本地变量(这个时候由于是初始化,所以添加的值为null),否则创建threadLocals变量,同样添加的值为null。
1 public T get() { 2 //(1)获取当前线程 3 Thread t = Thread.currentThread(); 4 //(2)获取当前线程的threadLocals变量 5 ThreadLocalMap map = getMap(t); 6 //(3)如果threadLocals变量不为null,就可以在map中查找到本地变量的值 7 if (map != null) { 8 ThreadLocalMap.Entry e = map.getEntry(this); 9 if (e != null) { 10 @SuppressWarnings("unchecked") 11 T result = (T)e.value; 12 return result; 13 } 14 } 15 //(4)执行到此处,threadLocals为null,调用该更改初始化当前线程的threadLocals变量 16 return setInitialValue(); 17 } 18 19 private T setInitialValue() { 20 //protected T initialValue() {return null;} 21 T value = initialValue(); 22 //获取当前线程 23 Thread t = Thread.currentThread(); 24 //以当前线程作为key值,去查找对应的线程变量,找到对应的map 25 ThreadLocalMap map = getMap(t); 26 //如果map不为null,就直接添加本地变量,key为当前线程,值为添加的本地变量值 27 if (map != null) 28 map.set(this, value); 29 //如果map为null,说明首次添加,需要首先创建出对应的map 30 else 31 createMap(t, value); 32 return value; 33 }3、remove方法的实现
remove方法判断该当前线程对应的threadLocals变量是否为null,不为null就直接删除当前线程中指定的threadLocals变量
1 public void remove() { 2 //获取当前线程绑定的threadLocals 3 ThreadLocalMap m = getMap(Thread.currentThread()); 4 //如果map不为null,就移除当前线程中指定ThreadLocal实例的本地变量 5 if (m != null) 6 m.remove(this); 7 }4.threadlocal源码分析总结: (1)每个Thread维护着一个ThreadLocalMap的引用 (2)ThreadLocalMap是ThreadLocal的内部类,用Entry来进行存储 (3)ThreadLocal创建的副本是存储在自己的threadLocals中的,也就是自己的ThreadLocalMap。 (4)ThreadLocalMap的键值为ThreadLocal对象,而且可以有多个threadLocal变量,因此保存在map中 (5)在进行get之前,必须先set,否则会报空指针异常,当然也可以初始化一个,但是必须重写initialValue()方法。 (6)ThreadLocal本身并不存储值,它只是作为一个key来让线程从ThreadLocalMap获取value。 5.原理: 首先,在每个线程Thread内部有一个ThreadLocal.ThreadLocalMap类型的成员变量threadLocals,这个threadLocals就是用来存储实际的变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)。初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals。然后在当前线程里面,如果要使用副本变量,就可以通过get方法在threadLocals里面查找。 6.注意: 重点来了,突然我们ThreadLocal是null了,也就是要被垃圾回收器回收了,但是此时我们的ThreadLocalMap生命周期和Thread的一样,它不会回收,这时候就出现了一个现象。那就是ThreadLocalMap的key没了,但是value还在,这就造成了内存泄漏。 解决办法:使用完ThreadLocal后,执行remove操作,避免出现内存溢出情况。 ThreadLocal不支持继承性 ThreadLocal类是不能提供子线程访问父线程的本地变量的,而InheritableThreadLocal类则可以做到 题外基础补充:
①强引用:Java中默认的引用类型,一个对象如果具有强引用那么只要这种引用还存在就不会被GC。
②软引用:简言之,如果一个对象具有弱引用,在JVM发生OOM之前(即内存充足够使用),是不会GC这个对象的;只有到JVM内存不足的时候才会GC掉这个对象。软引用和一个引用队列联合使用,如果软引用所引用的对象被回收之后,该引用就会加入到与之关联的引用队列中
③弱引用(这里讨论ThreadLocalMap中的Entry类的重点):如果一个对象只具有弱引用,那么这个对象就会被垃圾回收器GC掉(被弱引用所引用的对象只能生存到下一次GC之前,当发生GC时候,无论当前内存是否足够,弱引用所引用的对象都会被回收掉)。弱引用也是和一个引用队列联合使用,如果弱引用的对象被垃圾回收期回收掉,JVM会将这个引用加入到与之关联的引用队列中。若引用的对象可以通过弱引用的get方法得到,当引用的对象呗回收掉之后,再调用get方法就会返回null
④虚引用:虚引用是所有引用中最弱的一种引用,其存在就是为了将关联虚引用的对象在被GC掉之后收到一个通知。(不能通过get方法获得其指向的对象)
标签:map,浅谈,threadlocal,threadLocals,引用,线程,null,变量 来源: https://www.cnblogs.com/zuoyi2319516228/p/15597438.html