ThreadLocal

64 阅读1分钟

我们先看一组概念:

强引用: A a = new A();  a指向a对象的指向为强引用,不设为空,垃圾回收器不会回收。
软引用: gc如果空间不够就会回收软引用持有的对象
弱引用: 发生gc就会回收弱引用持有的对象
虚引用: 用来跟踪对象被垃圾回收的活动
ThreadLocal和弱引用有关联,我们看下弱引用持有对象是否gc时会被回收:

代码:

public static void main(String[] args) {
    TreeNode treeNode = new TreeNode();
    WeakReference<TreeNode> weakReference = new WeakReference<>(treeNode);
    treeNode = null;
    System.out.println("gc前: " + weakReference.get());
    System.gc();
    System.out.println("gc后: " + weakReference.get());
}

1658930077(1).png

接下来我们谈ThreadLocal:

我们知道Thread类中有个成员变量ThreadLocalMap,这保证了每个线程操作的是自己的内容,是个map,他的key是一个弱引用,指向ThreadLocal对象,他的值是用户设置的。

我们看一段代码:

public class MyThreadLocal {
    private static ThreadLocal<String> threadLocal = new ThreadLocal<>();

    public static void main(String[] args) {
        threadLocal.set("这是在主线程中");
        System.out.println("threadLocal = " + threadLocal.get());
        threadLocal.remove();
    }
}

解释:

threadLocal指向了ThreadLocal对象,是个强引用,主线程的ThreadLocalMap里的key也指向了ThreadLocal对象,是个弱引用,value指向了"这是在主线程中".

你是否很奇怪,key是弱引用,持有的对象随时会被gc回收,那怎么保证使用呢?
threadLocal指向该对象是强引用,只要不设置为null,就不会回收ThreadLocal对象。

当threadLocal被设置为null后,下次gc,ThreadLocal对象被回收。
当key为null时,value就难回收了,所以我们不用的时候需要调用remove方法清掉map里的记录。