搞懂ThreadLocal

152 阅读2分钟

java中的引用

  1. 强引用:使用最普遍的引用;内存不足时,即使抛出OOM也不会被回收。
Object obj = new Object();

如果期望对象被回收,显示的将引用指向null则在gc触发时会自动回收。

  1. 软引用:描述一些有用但不是必须的对象;只有在内存不足的时候才会回收。 软引用通过SoftRefference创建;主要应用场景是缓存。

  2. 弱引用:用来描述非必须的对象,gc时无论内存是否充足都会对弱引用关联的对象进行回收。 弱引用通过WeakRefference创建。 (显示的通过System.gc()通知jvm进行垃圾回收,但jvm不一定会立即执行)

  3. 虚引用:不影响对象的生命周期,通过虚引用创建关联和没关联一样。 通过PhantomReference创建;任何时候都可能被gc回收。 主要用来跟踪对象被垃圾回收的活动。

ThreadLocal

  • ThreadLocal 为变量在每个线程中创建了一个副本,这样每个线程都可以访问自己内部的副本变量。
  • 使用:
public static void main(String[] args) {
    ThreadLocal<String> tl = new ThreadLocal<>();
    IntStream.range(0,10).forEach(i -> new Thread(()-> {
        tl.set(Thread.currentThread().getName() + ":" + i);
        System.out.println(tl.get());

    }).start());

    tl.remove();

}
  • ThreadLocalMap 为 ThreadLocal 的一个静态内部类,里面定义了Entry 来保存数据。而且是继承的弱引用。

  • 在Entry内部使用当前的threadlocal变量作为key,使用我们设置的value作为value。

  • 暂时还不理解: 为什么key使用弱引用? 如果使用强引用,当ThreadLocal 对象的引用(强引用)被回收了,ThreadLocalMap本身依然还持有ThreadLocal的强引用,如果没有手动删除这个key ,则ThreadLocal不会被回收,所以只要当前线程不消亡,ThreadLocalMap引用的那些对象就不会被回收, 可以认为这导致Entry内存泄漏。 目前对threadlocal的理解还不够深刻,后续可以再看看:blog.csdn.net/qq_35190492…

补充

FastThreadLocal是Netty中提供的高性能本地线程副本变量工具。在Netty的io.netty.util中提供了很多牛逼的工具。 FastThreadLocal有下面几个特点:

  1. 使用数组代替ThreadLocalMap存储数据,从而获取更快的性能。(缓存行和一次定位,不会有hash冲突).
  2. 由于使用数组,不会出现Key回收,value没被回收的尴尬局面,所以避免了内存泄漏。