ThreadLocal源码解析以及常见面试题

ThreadLocal源码解析

ThreadLocalMap

ThreadLocalMap属于ThreadLocal的一个静态内部类


public class Thread implements Runnable {
	ThreadLocal.ThreadLocalMap threadLocals = null;

}


public class ThreadLocal<T>{

	//这里是真正存储数据的地方
	ThreadLocal.ThreadLocalMap threadLocals = null;
    
    //这是一个静态内部类    
    static class ThreadLocalMap {
	       static class Entry extends WeakReference<ThreadLocal<?>> {
	       }
	}
}

面试题

一、ThreadLocal存储的key,value分别是什么?存储在什么地方?

  1. ThreadLocal存储的key是new ThreadLocal()对象本身,所以一个ThreadLocal对象只有一个Value,多次set会覆盖。
  2. 存储的位置在Thread的成员变量中,如下所示:
    ThreadLocal.ThreadLocalMap threadLocals = null;
    一个Thread只有一个ThreadLocalMap,ThreadLocalMap中有一个entry数组,如下所示:
    private Entry[] table;

Entry的所有代码如下,我们的Value就存储在Entry的value中。

static class Entry extends WeakReference<ThreadLocal<?>> {
      /** The value associated with this ThreadLocal. */
      Object value;

      Entry(ThreadLocal<?> k, Object v) {
            super(k);
            value = v;
      }
}

二、一个ThreadLocal只有一个Value,为什么要使用Entry数组存储呢?其他的空间是不是浪费?

因为一个Thread只有一个ThreadLocalMap,而我们却可以在一个Thread线程中创建多个ThreadLocal对象,如下所示:

public class Test{
	private ThreadLocal td1 = new ThreadLocal();
	private ThreadLocal td2 = new ThreadLocal();
    private ThreadLocal td3 = new ThreadLocal();
    // 我们可以创建多个ThreadLocal
}

当多个ThreadLocal对象set值时,我们会根据ThreadLocal对象的hashcode计算出其所在的Entry数组的下标位置,计算方式如下(是不是跟HashMap计算数组下标类似)
int i = key.threadLocalHashCode & (len-1);(相当于取余数)

总结:所以使用Entry数组存储ThreadLocal的value的是为了一个Thread中创建多个ThreadLoca对象。

三、Entry为什么要继承WeakReference弱引用呢?

1.观察如下代码,当method()调用完成后程序继续执行,此时ThreadLocal的对象引用会被回收掉,如果Entry是强引用的情况下就会发送内存泄漏。

public void test(){
    method();
    //程序继续执行
    //more code ,继续处理业务逻辑
}

public void method(){
	ThreadLocal td = new ThreadLocal();
	td.set("1GB");
}

在这里插入图片描述

原因分析:
当继续处理业务逻辑时,method方法已经执行完成了,ThreadLocal的引用(td)已经断开,按理应该回收堆中的ThreadLocal实例,可是却被key(红色)所引用导致无法回收,由于主线程对象一直还在运行,所以ThreadLocalMap实例一直无法回收,导致Entry数组中的key和value也就无法回收调,此时就发送了内存泄漏。

解决方案;

如果此时Entry替换成弱引用(黄色虚线),则ThreadLocal只剩下一个弱引用,会立即被回收,此时Entry对象会被回收,那么value自然也会被回收调。

关于弱引用的规范如下:

垃圾回收器一旦发现只具有弱引用的对象,不管当前内存空间是否足够,都会回收它的内存

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值