ThreadLocal原理和源码

简介

ThreadLocal的实例代表了一个线程局部的变量,每条线程都只能看到自己的值,并不会意识到其它的线程中也存在该变量。
 

实现方法

在ThreadLocal类中定义了一个ThreadLocalMap,每一个Thread都有一个ThreadLocalMap,ThreadLocalMap内部有一个Entry数组,key是ThreadLocal,value就是我们定义的变量副本。
 
 

使用方式

例如我们知道SimpleDateFormat是线程不安全的,多线程使用可以使用ThreadLocal
//声明
 ThreadLocal<SimpleDateFormat> dateFormatter = new ThreadLocal<SimpleDateFormat>();
//调用
dateFormatter.get().format(result);
 

源码

get()方法

 
1、获取当前线程t;
2、返回当前线程t的成员变量ThreadLocalMap(以下简写map);
3、map不为null,则获取以当前线程为key的ThreadLocalMap的Entry(以下简写e),如果e不为null,则直接返回该Entry的value;
4、如果map为null或者e为null,返回setInitialValue()的值。setInitialValue()调用重写的initialValue()返回新值(如果没有重写initialValue将返回默认值null),并将新值存入当前线程的ThreadLocalMap(如果当前线程没有ThreadLocalMap,会先创建一个)
 
具体看到源码就知道:
public T get()
{
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }
 
  在get函数中,首先获取到当前的线程t,再根据t获取ThreadLocalMap。下面试getMap()函数:
ThreadLocalMap getMap(Thread t)
{
     return t.threadLocals;
}
 
    如果没有找到对应的map,就会调用setInitialValue创建map
private T setInitialValue()
{
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
}
 
可以看到,每个线程都会有对应的 ThreadLocalMap,key为当前的ThreadLocal示例,value为需要设置的值
 
 
 

set()方法

HashMap使用 链地址法 来解决Hash冲突,而ThreadLocalMap使用 开放地址法 来解决Hash冲突。
public void set(T value)
 {
     Thread t = Thread.currentThread();
     ThreadLocalMap map = getMap(t);
     if (map != null)
         map.set(this, value);
     else
         createMap(t, value);
 }
 
set函数同样是先获取ThreadLocalMap类型的变量map。如果不存在就会创建map
 
void createMap(Thread t, T firstValue)
{
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}
 
 
ThreadLocalMap定义
static class ThreadLocalMap
{
    static class Entry extends WeakReference<ThreadLocal>
    {
            /** The value associated with this ThreadLocal. */
            Object value;
            Entry(ThreadLocal k, Object v)
     {
                super(k);
                value = v;
       }
     }   
    ...
}
 
 
 
 
 
ref.
 
 
 
   
   
   
   
 
 
 
 
欢迎关注我公众号:

发表回复

您的电子邮箱地址不会被公开。

粤ICP备17041560号-2