主要用途

  1)设计线程安全的类

  2)存储无需共享的线程信息

设计思路

ThreadLocalMap原理

1)对象存储位置-->当前线程的ThreadLocalMap

  ThreadLocalMap是在ThreadLocal中定义的静态内部类,用于存放线程的信息,以ThreadLocal或InheritableThreadLocal为key,对象为value.每个Thread都有两个ThreadLocalMap,如下

    /* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
   //存放线程自己的信息,注册ThreadLocal
ThreadLocal.ThreadLocalMap threadLocals = null; /*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
//父线程信息的拷贝,注册InheritableThreadLocal
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

  2)ThreadLocalMap,实现自定义Map,实现存储的大致原理如下

        /**
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object). Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table. Such entries are referred to
* as "stale entries" in the code that follows.
*/
     //封装ThreadLocal和对象
static class Entry extends WeakReference<ThreadLocal> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal k, Object v) {
super(k);
value = v;
}
}
/**
* The table, resized as necessary.
* table.length MUST always be a power of two.
*/
     //数组存放entry
private Entry[] table;
private Entry getEntry(ThreadLocal key) {
        //利用ThreadLocal的哈希值属性定位在table中的位置
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);
}

ThreadLocal原理

    /**
* Returns the value in the current thread's copy of this
* thread-local variable. If the variable has no value for the
* current thread, it is first initialized to the value returned
* by an invocation of the {@link #initialValue} method.
*
* @return the current thread's value of this thread-local
*/
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t); //获取当前线程的ThreadLocalMap
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
/**
* Sets the current thread's copy of this thread-local variable
* to the specified value. Most subclasses will have no need to
* override this method, relying solely on the {@link #initialValue}
* method to set the values of thread-locals.
*
* @param value the value to be stored in the current thread's copy of
* this thread-local.
*/
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value); //key=ThreadLocal,value=对象
else
createMap(t, value);
}
/**
* Get the map associated with a ThreadLocal. Overridden in
* InheritableThreadLocal.
*
* @param t the current thread
* @return the map
*/
ThreadLocalMap getMap(Thread t) {
return t.threadLocals; //获取当前线程的ThreadLocalMap
}
protected T initialValue() { //初始化ThreadLocal时,预定义初始化value,默认为null
return null;
}
/**
* Variant of set() to establish initialValue. Used instead
* of set() in case user has overridden the set() method.
*
* @return the initial value
*/
private T setInitialValue() {
T value = initialValue(); //获取ThreadLocal初始化的value
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
/**
* Create the map associated with a ThreadLocal. Overridden in
* InheritableThreadLocal.
*
* @param t the current thread
* @param firstValue value for the initial entry of the map
* @param map the map to store.
*/
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue); //定义当前线程的 ThreadLocal.ThreadLocalMap threadLocals
}

  注意,在new ThreadLocal时可以通过T java.lang.ThreadLocal.initialValue()定义存储的初始化对象

InheritableThreadLocal原理

  主要实现

  1)覆盖ThreadLocal的方法,将存储位置定位到ThreadLocal.ThreadLocalMap inheritableThreadLocals

  2)在从父线程获取inheritableThreadLocals,通过childValue定制复制的行为.

  源码如下

public class InheritableThreadLocal<T> extends ThreadLocal<T> { //ThreadLocal的子类
/**
* Computes the child's initial value for this inheritable thread-local
* variable as a function of the parent's value at the time the child
* thread is created. This method is called from within the parent
* thread before the child is started.
* <p>
* This method merely returns its input argument, and should be overridden
* if a different behavior is desired.
*
* @param parentValue the parent thread's value
* @return the child thread's initial value
*/
protected T childValue(T parentValue) {
return parentValue; //在ThreadLocalMap(ThreadLocalMap parentMap)时,定制复制行为
}
/**
* Get the map associated with a ThreadLocal.
*
* @param t the current thread
*/
ThreadLocalMap getMap(Thread t) {
return t.inheritableThreadLocals; //重定向到线程的对应位置
}
/**
* Create the map associated with a ThreadLocal.
*
* @param t the current thread
* @param firstValue value for the initial entry of the table.
* @param map the map to store.
*/
void createMap(Thread t, T firstValue) {
t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue); //重定向到线程的对应位置
}
}

ThreadLocal源码解析的更多相关文章

  1. Java 8 ThreadLocal 源码解析

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

  2. 一步一步学多线程-ThreadLocal源码解析

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

  3. ThreadLocal源码解析-Java8

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

  4. Thread、ThreadLocal源码解析

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

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

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

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

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

  7. ThreadLocal 类 的源码解析以及使用原理

    1.原理图说明 首先看这一张图,我们可以看出,每一个Thread类中都存在一个属性 ThreadLocalMap 成员,该成员是一个map数据结构,map中是一个Entry的数组,存在entry实体, ...

  8. 2018/3/3 解析ThreadLocal源码

    今天听到一个老哥说道ThreadLocal在源码设计上面的一些好处,于是决定把ThreadLocal源码彻底分析一下. 首先,我们来看下set方法 可以看到,这个方法里,先获得了当前线程,之后将当前线 ...

  9. EventBus源码解析 源码阅读记录

    EventBus源码阅读记录 repo地址: greenrobot/EventBus EventBus的构造 双重加锁的单例. static volatile EventBus defaultInst ...

随机推荐

  1. httpclient源码分析之 PoolingHttpClientConnectionManager 获取连接

    PoolingHttpClientConnectionManager是一个HttpClientConnection的连接池,可以为多线程提供并发请求服务.主要作用就是分配连接,回收连接等.同一个rou ...

  2. JAVA循环依赖

    最近看到一个问题:如果有两个类A和B,A类中有一个B的对象b,B类中有一个A的对象a,那么如何解决这两个类的相互依赖关系呢? 示例代码1 public class Test{ public stati ...

  3. Knockout Mvc Compoment FrameSet

    Knockout Mvc Compoment FrameSet 框架文件结构 01-   网站(表现层),mvc主要作用视图展示. 02-   模型(Model),主要作用承载视图数据结构,网站前后台 ...

  4. zookeeper的安装与部署-伪集群

    1.Zookeeper的下载与解压     通过后面的链接下载Zookeeper:    Zookeeper下载在此我们下载zookeeper-3.4.5下载后解压至安装目录下,本文我们解压到目录:/ ...

  5. ksum问题

    2sum: Given an array of integers, return indices of the two numbers such that they add up to a speci ...

  6. Maven基础学习(一)—Maven入门

    一.概述      Maven是一个项目管理工具,它包含了一个项目对象模型(Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管 ...

  7. JavaWeb总结(七)—JSTL标签库

    一.JSTL标签库介绍 JSTL标签库的使用时为了弥补HTML标签的不足,规范自定义标签的使用而诞生的.使用JSTL标签的目的是不希望在JSP中出现Java逻辑代码. 二.JSTL标签库的分类 1.核 ...

  8. Java将一个目录下的所有数据复制到另一个目录下

    /* 将"C:\\JavaProducts\\Source"下的所有数据复制到"C:\\Target"下 */ import java.io.*; public ...

  9. kafka分布式消息队列介绍以及集群安装

    简介 首先简单说下对kafka的理解: 1.kafka是一个分布式的消息缓存系统: 2.kafka集群中的服务器节点都被称作broker 3.kafka的客户端分为:一是producer(消息生产者) ...

  10. 你绝对想不到R文件找不到(cannot resolve symbol R)的原因

    你绝对想不到R文件找不到(cannot resolve symbol R)的原因 最近在项目开发中 Android Studio 的 R 文件突然找不到了.IDE 中出现了以下提示 cannot re ...