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原理和源码/

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » ThreadLocal原理和源码

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址