ThreadLocal源码解析

目录

set(T value)源码:

get()源码:

remove()源码:

总结 


 

前面讲Jdbc连接时涉及到ThreadLocal的内容由于要解释的东西太多,所以另开一篇解释

ThreadLocal里面的几个方法

1、set(T value) 设置ThreadLocal中当前线程共享变量的值。

2、get() 获取ThreadLocal中当前线程共享变量的值。

3、remove()移除ThreadLocal中当前线程共享变量的值

set(T value)源码:

public void set(T value) {
//获取当前线程
        Thread t = Thread.currentThread();
//在ThreadLocal 中,以t来获取当前线程的一个ThreadLocalMap
        ThreadLocalMap map = getMap(t);
//如果ThreadLocal中有这个map,就把当前类和对应的值传进去
        if (map != null)
            map.set(this, value);
//如果没有这个map,就新建一个t线程的ThreadLocalMap,并将value值传进去
        else
            createMap(t, value);
    }

//在创建t线程的ThreadLocalMap时,同样要把当前类作为Key值传入此ThreadLocalMap中
void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

 

get()源码:

public T get() {
//获取当前线程
        Thread t = Thread.currentThread();
//获取当前线程的map
        ThreadLocalMap map = getMap(t);
//判断当前线程的map是否存在,不为空
        if (map != null) {
//如果存在,就获取当前对象的Entry键值对
            ThreadLocalMap.Entry e = map.getEntry(this);
//判断这个键值对是否为空
            if (e != null) {
//如果不是空,就返回对应的value值
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
//此处是当前线程的map不存在,返回setInitialValue,进程初始化
        return setInitialValue();
    }

private T setInitialValue() {
//调用initialValue方法,此方法是初始化ThreadLocal的方法,
        T value = initialValue();
//下面一段代码是再次判断ThreadLocal中是否有当前线程的map
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
//根据初始化的内容,决定是在map中插入值,还是新建map插入值
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }
//初始化ThreadLocal的方法,一般会在创建ThreadLocal对象时重写该方法,确保初始化时,不至于为null
protected T initialValue() {
        return null;
    }

remove()源码:

public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }

移除当前线程的map

PS

1、ThreadLocalMap 是ThreadLocal里面的一个内部类,相当于Map,是个双列集合,但是是以(T t,ThreadLocalMap())的形式存储数据的,ThreadLocalMap()是内部类ThreadLocalMap内的构造方法。

2、为了防止内存溢出,在每条线程任务执行完后,要调用remove方法溢出ThreadLocal中的连接

3、ThreadLocalMap是根据线性探测的方法来插入数据的。所谓线性探测,就是根据初始key的hashcode值确定元素在table数组中的位置,如果发现这个位置上已经有其他key值的元素被占用,则利用固定的算法寻找一定步长的下个位置,依次判断,直至找到能够存放的位置。ThreadLocalMap解决Hash冲突的方法就是利用步长加1或者减1,来寻找下一个相邻的位置,直至找到合适的位置

4、因为ThreadLocalMap处理hash冲突的复杂性,为了提高性能,建议每个线程只存放一个变量。样的话所有的线程存放到map中的Key都是相同的ThreadLocal,如果一个线程要保存多个变量,就需要创建多个ThreadLocal,多个ThreadLocal放入Map中时会极大的增加Hash冲突的可能。

tips:下面将我读到的一篇关于ThreadLocal写的不错的文章连接附上,方便查阅。

ThreadLocal深度解析

总结 

 ThreadLocal通过给不同的线程分配各自特有的map,来区分不同的线程,并在每个map中存入以当前对象为key,存储数据为value的Entry键值对来区分不同线程的任务,确保,当前线程只能处理当前线程的数据,不能处理其他线程的数据。

能力尚浅,有待进步,如有不足,不吝赐教!

你可能感兴趣的:(技术整理)