ThreadLocal
线程封闭
将某个对象封闭在一个线程当中,仅在一个线程当中访问,则可以避免使用同步。
强软弱虚
- 强引用:类似于 Object obj = new Object() 这种引用关系,无论在任何情况下,只要存在强引用关系,被引用对象就不会被回收掉。
- 软引用:软引用关联的对象在堆内存充足时会一直存在,但是在系统即将发生内存溢出前,会针对软引用对象进行第二次回收,回收掉软引用关联的对象。如果回收后还是没有足够的内存空间,才会发生内存溢出。适用于缓存场景。
- 弱引用:弱引用关联的对象只能生存到下一次垃圾回收,当垃圾回收执行时,无论内存是否足够都会回收掉弱引用关联的对象。
- 虚引用:一个对象是否有虚引用不会对其生存时间构成影响,也无法通过虚引用来获取对象实例,唯一的目的就是在这个对象被回收时收到一个系统通知。可以使用它来管理堆外内存,在Java中使用DirectByteBuffer来管理堆外内存,我们可以给这个对象加一个虚引用,在这个对象被回收后会受到一个系统通知,然后去回收掉这个对象所管理的堆外内存。
作用
一个线程可以通过ThreadLocal对象来给当前线程绑定一个对象,然后在需要的时候通过对应的ThreadLocal对象(key)来获取绑定的值。将这个对象封闭在了当前线程当中,仅在当前线程当中访问,可以避免使用同步。
注:
- 使用一个ThreadLocal对象可以为当前线程绑定一个对象,通过多个不同的ThreadLocal对象可以绑定多个对象。
- 多个线程可以共用一个ThreadLocal对象。
- 当前线程以ThreadLocal对象为key,value是指向绑定对象的引用。所以通过ThreadLocal对象获取到绑定对象后修改属性,原对象也会被修改。
实现
过程:每个线程内部都有一个Map对象,key是ThreadLocal,value是要绑定的对象。通过ThreadLocal对象给线程绑定对象其实就是先获取当前线程t,然后获取到线程t内部的Map对象,然后向这个Map对象中插入以当前ThreadLocal对象为key,待绑定数据为value的Entry,这个Entry继承自WeakReference,它的key是一个弱引用,指向ThreadLocal对象。
防止内存泄露
- 线程内部的Map的每一个项Entry都是继承自WeakReference的,它的key是一个弱引用,指向ThreadLocal对象,所以当指向ThreadLocal对象的强引用为null时,ThreadLocal对象会被GC回收掉。
- 在绑定数据不需要时,需要手动的调用ThreadLocal对象的remove()方法,从当前线程的Map中清除这个ThreadLocal对象所对应的value。
如果你想了解更多我对编程和人生的思考,请关注公众号:青云学斋