上网查看了很多篇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. python自动化运维学习第一天--day1

    学习python自动化运维第一天自己总结的作业 所使用到知识:json模块,用于数据转化sys.exit 用于中断循环退出程序字符串格式化.format字典.文件打开读写with open(file, ...

  2. Oracle的用户、角色以及权限相关操作

    1.创建用户create user KD identified by 123456;2.授予连接数据库的权限grant connect to KD;3.将Scott用户的emp表授权给KD可以查询gr ...

  3. Python 操作 MYSQL

    本文介绍了 Python 操作 MYSQL.执行 SQL 语句.获取结果集.遍历结果集.取得某个字 段.获取表字段名.将图片插入数据库.执行事务等各种代码实例和详细介绍,代码居多, 是一桌丰盛唯美的代 ...

  4. BufferedWriterTest

    public class BufferedWriterTest { public static void main(String[] args) { try { //创建一个FileWriter 对象 ...

  5. usaco training 4.2.4 Cowcycles 题解

    Cowcycles题解 Originally by Don Gillies [International readers should note that some words are puns on ...

  6. js验证表单密码、用户名是否输入--JS的简单应用

    在登录.注册时,我们经常会遇到下面这种情况,如果我们没有输入用户名.密码时,系统会弹出提示框.提示框信息提示内容是我们密码没有输入密码或者用户名等.那么这样的弹出框效果是如何实现的呢?文章标题既然与j ...

  7. ES6简介

    function fn(){ return 100; } let name='sui'; let age=19; let sui={ name, age, ["pro"+fn()] ...

  8. es6的模块化编程

    es6的模块化编程 基本用法 es6 中新增了两个命令 export 和 import , export 命令用于规定模块的对外接口,import 命令用于输入其他模块提供的功能. 一个模块就是一个独 ...

  9. table初始化

    table, th , td { border: 1px solid grey; border-collapse: collapse; padding: 5px;}

  10. javascript数组(1) ——sort的工作原理及其他数组排序方法

    一说到数组排序,最直观的想法就是用sort啊! 请问不用使用sort方法还可以使用什么方法进行数组排序? 比如 :  快速排序法.合并排序法.冒泡排序法.选择排序法.插入排序法.布尔排序法.交互排序. ...