转载

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.

https://www.cnblogs.com/xujian2014/p/5777849.html

https://blog.csdn.net/u010887744/article/details/54730556

欢迎关注我公众号: ThreadLocal原理和源码
原文  https://okayjam.com/index.php/2019/04/03/threadlocal原理和源码/
正文到此结束
Loading...