我们先看一组概念:
强引用: 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());
}
接下来我们谈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里的记录。