多线程与高并发(五)--ThreadLocal、强软弱虚引用
ThreadLocal
- ThreadLocal 适用于每个线程需要自己独立的实例且该实例需要在多个方法中被使用,也即变量在线程间隔离而在方法或类间共享的场景。
- ThreadLocal的set方法源码
/** * Sets the current thread's copy of this thread-local variable * to the specified value. Most subclasses will have no need to * override this method, relying solely on the {@link #initialValue} * method to set the values of thread-locals. * * @param value the value to be stored in the current thread's copy of * this thread-local. */ public void set(T value) { // 获取当前线程 Thread t = Thread.currentThread(); /** * 拿到的这个map是当前线程的一个变量, * 也就是说ThreadLocal是把变量存到当前线程的一个map中了 */ ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }
强引用
强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。
软引用
如果一个对象只具有软引用,则内存空间充足时,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。
弱引用
- 弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
- 典型应用是ThreadLocal。ThreadLocal在设置值时,key是当前的ThreadLocal对象,设置到map中时是一个弱引用。
/** * The entries in this hash map extend WeakReference, using * its main ref field as the key (which is always a * ThreadLocal object). Note that null keys (i.e. entry.get() * == null) mean that the key is no longer referenced, so the * entry can be expunged from table. Such entries are referred to * as "stale entries" in the code that follows. */ // 这是ThreadLocal的一个内部类,继承自弱引用。 static class Entry extends WeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } }
- 为什么Entry要使用弱引用?
- 若是强引用,即使tl=null(key指向的ThreadLocal对象),但是key的引用依然指向ThreadLocal对象,所以会有内存泄漏的风险,而使用弱引用则不会。但还是存在内存泄漏风险,ThreadLocal被回收,key的值变为null,则导致整个value再也无法被访问到,因此依然存在内存泄漏风险。所以当值不使用时要remove。
- 为什么Entry要使用弱引用?
虚引用
-
虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
- 主要用来管理堆外内存,NIO中就有使用。

浙公网安备 33010602011771号