ThreadLocal为每个使用它的线程提供一个变量的副本。
ThreadLocal中的主要方法:
  1. public void set(T value)
public void set(T value) {Thread t = Thread.currentThread();//取得线程t的ThreadLocalMap对象ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);}

先调用Thread类的静态方法获得当前线程的Thread对象,每个线程对应的Thread对象都有一个ThreadLocalMap对象的引用,如下。
  ThreadLocal.ThreadLocalMap threadLocals = null;     //Thread类中

然后获得当前线程的ThreadLocalMap对象
ThreadLocalMap getMap(Thread t) {     //ThreadLocal类内的方法return t.threadLocals;}

如果不为空就调用set方法,如果为空就调用createMap方法,传入参数为ThreadLocalMap为空的Thread对象,和T类型的firstValue
 void createMap(Thread t, T firstValue) {t.threadLocals = new ThreadLocalMap(this, firstValue);}

使用ThreadLocalMap的重载构造器,构造Thread对象的ThreadLocalMap,传入参数为当前的ThreadLocal对象,和firstValue
 private static final int INITIAL_CAPACITY = 16;          //ThreadLocalMap中定义的

 private final int threadLocalHashCode = nextHashCode();          //ThreadLocal中定义的

 ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {table = new Entry[INITIAL_CAPACITY];int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);table[i] = new Entry(firstKey, firstValue);size = 1;setThreshold(INITIAL_CAPACITY);}

i为threadLocal对象的哈希值和Entry数组的大小-1的二进制值(1111)的操作结果,这样能保证存储在数组的每一个位置的概率相同。
创建一个Entry(键值对)数组,存放下标为threadLocal对象的哈希值和1111的与操作结果,存放对象的键为threadLocal对象,值为firstValue即set的值
firstValue对象存储在ThreadLocalMap对象维护的Entry类型数组 table内,下标为ThreadLocal对象和1111的与运算结果,entry的key为threadLocal对象
2.public Object get()方法:该方法返回当前线程所对应的线程局部变量
 public T get() {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) {ThreadLocalMap.Entry e = map.getEntry(this);if (e != null) {@SuppressWarnings("unchecked")T result = (T)e.value;return result;}}return setInitialValue();}

get方法,先获取当前线程的thread对象,再获取thread对象的threadLocalMap对象,然后根据当前的threadLocal对象取得table数组对应下标的Entry对象(因为存储的时候就是根据当前的ThreadLoca对象的Hash值存储的)
private Entry getEntry(ThreadLocal<?> key) {int i = key.threadLocalHashCode & (table.length - 1);Entry e = table[i];if (e != null && e.get() == key)return e;elsereturn getEntryAfterMiss(key, i, e);}

最后如果Thread对象的ThreadLocalMap为空的话,就调用setInitialValue方法,该方法初始化map并且放入null ( initialValue的返回值为null ),可以通过覆盖该方法修改没有set的时候的初始值
 private T setInitialValue() {T value = initialValue();Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);return value;}

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

ThreadLocal的remove方法先获取当前线程的Map对象,然后调用Map的remove方法,删除entry
总结:
          对于非线程安全的变量可以将它封装进ThreadLocal中,在调用的时候不是直接引用而是使用ThreadLocal的set和get方法
          
          线程调用set方法:
          放入当前线程的ThreadLocalMap中,key为ThreadLocal的hashCode

转载于:https://www.cnblogs.com/coderlynn/p/8654473.html

ThreadLocal总结(jdk1.8源码)相关推荐

  1. 【JUC】JDK1.8源码分析之ArrayBlockingQueue(三)

    一.前言 在完成Map下的并发集合后,现在来分析ArrayBlockingQueue,ArrayBlockingQueue可以用作一个阻塞型队列,支持多任务并发操作,有了之前看源码的积累,再看Arra ...

  2. 【集合框架】JDK1.8源码分析之HashMap(一)

    转载自  [集合框架]JDK1.8源码分析之HashMap(一) 一.前言 在分析jdk1.8后的HashMap源码时,发现网上好多分析都是基于之前的jdk,而Java8的HashMap对之前做了较大 ...

  3. 【集合框架】JDK1.8源码分析HashSet LinkedHashSet(八)

    一.前言 分析完了List的两个主要类之后,我们来分析Set接口下的类,HashSet和LinkedHashSet,其实,在分析完HashMap与LinkedHashMap之后,再来分析HashSet ...

  4. JDK1.8源码分析:可重入锁ReentrantLock和Condition的实现原理

    synchronized的用法和实现原理 synchronized实现线程同步的用法和实现原理 不足 synchronized在线程同步的使用方面,优点是使用简单,可以自动加锁和解锁,但是也存在一些不 ...

  5. JDK1.1源码学习之官方文档与代码结构

    浩哥带你学习JDK1.1源码--第2天 1. 阅读源码那点事 2. JDK 1.1.8源码结构 1. 阅读源码那点事 在上一篇的文章中,进入Java官网的档案袋里面,可以看到文档有两个下载链接:一个日 ...

  6. hashmap实现原理_Java中HashMap底层实现原理(JDK1.8)源码分析

    在JDK1.6,JDK1.7中,HashMap采用位桶+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里.但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依 ...

  7. 基于JDK1.8---HashMap源码分析

    基于JDK1.8-HashMap源码简要分析 HashMap继承关系 HashMap:根据键的 hashCode 值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不 ...

  8. JDK1.8源码(三)——java.lang.String 类

    String 类也是java.lang 包下的一个类,算是日常编码中最常用的一个类了,那么本篇博客就来详细的介绍 String 类. 1.String 类的定义 public final class ...

  9. JDK1.8源码分析之HashMap(一) (转)

    一.前言 在分析jdk1.8后的HashMap源码时,发现网上好多分析都是基于之前的jdk,而Java8的HashMap对之前做了较大的优化,其中最重要的一个优化就是桶中的元素不再唯一按照链表组合,也 ...

  10. Java面试绕不开的问题: Java中HashMap底层实现原理(JDK1.8)源码分析

    这几天学习了HashMap的底层实现,但是发现好几个版本的,代码不一,而且看了Android包的HashMap和JDK中的HashMap的也不是一样,原来他们没有指定JDK版本,很多文章都是旧版本JD ...

最新文章

  1. 使用C#开发数据库应用系统
  2. 七十八、SpringBoot监听rabbitmq和创建交换器,队列
  3. Java NIO系列教程(四) Scatter/Gather
  4. 安装openJDK 8
  5. iOS开发实用技术之推送-应用间跳转-社交分享
  6. mysql里面手动关闭_MySQL 启动与关闭(手动与自动)
  7. 常见对象之String类
  8. 电信基础设施共建共享
  9. Python爬虫整站爬取安居客新房房源数据
  10. Kaptcha简单使用
  11. 用于空间搜索的四叉树
  12. Matlab中axis函数使用
  13. 东软始业教育2021(注意看得分88分)
  14. 算符优先分析java程序_算符优先分析
  15. JSF——JSF 标签
  16. RK3288 LED驱动编写
  17. 常见的硬件数据通信协议
  18. Python自动生成软著60页代码
  19. 自定义边框的制作与换色(canvas与css3)
  20. GIEC2022第九届全球互联网经济大会12月在京举办

热门文章

  1. 苹果 Mac 上不显示外置硬盘?9 个必须尝试的修复方法
  2. 如何使用键盘快捷键在Mac上录制屏幕?
  3. 性能优化篇 - Performance(工具 api)
  4. eNSP模拟器拓扑图:浮动路由的实际作用和分析,默认路由的配置,抓包分析
  5. 麻烦缠身的高通“向前看”:关注服务器市场和5G
  6. 大会直击|伯明翰大学教授姚新:类脑计算研究中三个被遗忘的问题
  7. Adb connect监听指定的主机和端口/Adb监听Visual Studio Emulator for Android模拟器
  8. 计算2的任意次方[通用版]
  9. 快速打开 Mac OS X 隐藏的用户资源库文件夹
  10. Eclipse 跌落“神坛”,这款 IDE 后来居上!