上网查看了很多篇ThreadLocal的原理的博客,上来都是文字一大堆,费劲看了半天,大脑中也没有一个模型,想着要是能够有一张图明确表示出来ThreadLocal的设计该多好,所以就自己看了源码,画了一张图出来,立刻清晰不少。

根据源码代码理清ThreadLocal结构

 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();
}
 ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
 ThreadLocal.ThreadLocalMap threadLocals = null;
 private Entry getEntry(ThreadLocal<?> key) {
int i = key.threadLocalHashCode & (table.length - 1);
Entry e = table[i];
if (e != null && e.get() == key)
return e;
else
return getEntryAfterMiss(key, i, e);
}

  通过上面的代码可以看出来,在每个线程里面都保存了ThreadLocalMap,而ThreaLocalMap里面又存储了以ThreadLocal为键值的Entry数组。

  用一张图来表示更清楚

      

ThreatLocal的Set步骤

  先看ThreadLocal的set方法,我们看一下ThreatLocal具体是怎么操作的

 public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
 void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}

  通过上面的代码可以看出来ThreadLocal的存储

  1、  获取当前线程

  2、  获取到当前线程中的ThreadLocalMap

  3、  如果获取到的ThreadLocalMap不为null,就以当前ThreadLocal对象为键,以要插入的值为值,ThreadMapLocalMap中。

  4、  如果获取的的ThreadLocalMap为null,则创建一个ThreadLocalMap对象

ThreadLocal的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();
}
 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;
}

  通过上面的代码可以看出来ThreadLocal的Get步骤为

  1、  获取当前线程

  2、  根据当前线程获取线程中的ThreadLocalMap

  3、  如果获取到的ThreadLocalMap不为null,则以当前ThreadLocal为键,获取存储在ThreadLocalMap中的值并返回

  4、  如果获取到的ThreadLocalMap为null,则创建一个以当前对象为键的对象,以ThreadLocal设置的初始值为值,存入ThreadLocalMap中,然后返回。

ThreaLocal中的初始值设置

 protected T initialValue() {
return null;
}

  上面这个initalValue方法是在创建ThreadLocalMap时候的value值的默认初始值,代码中默认返回的是null,我们可以通过自己在代码中自己设计值。

一步一步学多线程-ThreadLocal源码解析的更多相关文章

  1. Java 8 ThreadLocal 源码解析

    Java 中的 ThreadLocal是线程内的局部变量, 它为每个线程保存变量的一个副本.ThreadLocal 对象可以在多个线程中共享, 但每个线程只能读写其中自己的副本. 目录: 代码示例 源 ...

  2. [Java多线程]-ThreadLocal源码及原理的深入分析

    ThreadLocal<T>类:以空间换时间提供一种多线程更快捷访问变量的方式.这种方式不存在竞争,所以也不存在并发的安全性问题. //-------------------------- ...

  3. ThreadLocal源码解析-Java8

    目录 一.ThreadLocal介绍 1.1 ThreadLocal的功能 1.2 ThreadLocal使用示例 二.源码分析-ThreadLocal 2.1 ThreadLocal的类层级关系 2 ...

  4. ThreadLocal源码解析

    主要用途 1)设计线程安全的类 2)存储无需共享的线程信息 设计思路 ThreadLocalMap原理 1)对象存储位置-->当前线程的ThreadLocalMap ThreadLocalMap ...

  5. Thread、ThreadLocal源码解析

    今天来看一下Thread和ThreadLocal类的源码. 一.Thread (1)首先看一下线程的构造方法,之后会说每种参数的用法,而所有的构造函数都会指向init方法 //空构造创建一个线程 Th ...

  6. ThreadLocal源码解析,内存泄露以及传递性

    我想ThreadLocal这东西,大家或多或少都了解过一点,我在接触ThreadLocal的时候,觉得这东西很神奇,在网上看了很多博客,也看了一些书,总觉得有一个坎跨不过去,所以对ThreadLoca ...

  7. Java ThreadLocal 的使用与源码解析

    GitHub Page: http://blog.cloudli.top/posts/Java-ThreadLocal-的使用与源码解析/ ThreadLocal 主要解决的是每个线程绑定自己的值,可 ...

  8. Java多线程9:ThreadLocal源码剖析

    ThreadLocal源码剖析 ThreadLocal其实比较简单,因为类里就三个public方法:set(T value).get().remove().先剖析源码清楚地知道ThreadLocal是 ...

  9. java多线程17:ThreadLocal源码剖析

    ThreadLocal源码剖析 ThreadLocal其实比较简单,因为类里就三个public方法:set(T value).get().remove().先剖析源码清楚地知道ThreadLocal是 ...

随机推荐

  1. 再谈AbstractQueuedSynchronizer:基于AbstractQueuedSynchronizer的并发类实现

    公平模式ReentrantLock实现原理 前面的文章研究了AbstractQueuedSynchronizer的独占锁和共享锁,有了前两篇文章的基础,就可以乘胜追击,看一下基于AbstractQue ...

  2. CSS三种引入方式:内联、页级、外联

    1.内联CSS 内联CSS也可称为行内CSS或者行级CSS,它直接在标签内部引入,显著的优点是十分的便捷.高效:但是同时也造成了不能够重用样式的缺点,如果代码行数到达一定长度不建议采用.通常内联CSS ...

  3. Tomcat管理页面配置

    详情参考:http://www.365mini.com/page/tomcat-manager-user-configuration.htm 修改$CATALINA_BASE/conf/tomcat- ...

  4. 第二章:2.9 总结一下 Django

    1. URLconf(URL configuration ) : 这个模块包含URL模式(正则表达式)到视图函数(view.py)的简单映射. 2. python 正则表达式: 解释: 通配符:r : ...

  5. CSS 选择器优先级问题

    <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> &l ...

  6. CSS 样式书写规范+特殊符号

    虽然我只是刚踏入web前端开发圈子.在一次次任务里头,我发觉每一次的css命名都有所不同和不知所措.脑海就诞生了一个想法--模仿大神的css命名样式. 毕竟日后工作上,是需要多个成员共同协作的.如果没 ...

  7. 浅谈Nginx负载均衡原理与实现

    1.Nginx能做什么? Nginx可以两件事: -- HTTP请求  经过官方测试Nginx可以承受5万的并发量.可用来做静态资源的图片服务器 --负载均衡,如下解释什么是负载均衡. 2.负载均衡 ...

  8. 快速了解cpu、核与线程

    作为一个后台开发人员,我想有必要了解这些基础知识.如果本文有不严谨或者疏忽的地方,请指正. cpu与核心 物理核 物理核数量=cpu数(机子上装的cpu的数量)*每个cpu的核心数 虚拟核 所谓的4核 ...

  9. SVN分支/合并操作小记

    一.前言 说来惭愧,鄙人从事开发多年,使用svn已经好几个年头了,但是却仅限于update.commit.compare之类的操作,最近想到github上学习别人写的NIO源码,顺便去熟悉git的使用 ...

  10. (转)log4j(三)——如何控制不同级别的日志信息的输出?

    一:测试环境与log4j(一)——为什么要使用log4j?一样,这里不再重述 1 老规矩,先来个栗子,然后再聊聊感受 package test.log4j.test3; import org.apac ...