ThreadLocal 简单解析

基于jdk1.8

ThreadLocal一定不陌生,开发中常用,也是面试里的常客了,但是往往我们可能只是知道该类的作用。学习该类对于个人的多线程编码能力是大有裨益的,同时也可以知道使用中需要注意的地方

ThreadLocal也叫本地线程变量,我们知道ThreadLocal为每个线程创建一个副本,线程隔离的。

主要有4个公共方法get、remove、set、withInitial
看看set和remove 有set,get、remove就没必要细看了一看就明白了。

1.set

public void set(T value) {
Thread t = Thread.currentThread();//获取当前线程、也是能隔离的本质
ThreadLocalMap map = getMap(t);//getMap比较简单 return t.threadLocals; 后面再看这个t.threadLocals
if (map != null)
map.set(this, value); //好说不就是类似map的put值么,但是注意key是this写死了,表明一个ThreadLocal对象只能存一个值
else
createMap(t, value); //空 new ThreadLocalMap(this, firstValue)
} t.threadLocals明显是线程类Thread中的变量 ThreadLocal.ThreadLocalMap threadLocals = null; 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;
}
}
private static final int INITIAL_CAPACITY = 16;
private Entry[] table;
private int threshold; //通过createMap初始化来看
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];//16的Entry数组
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);//数组位置
table[i] = new Entry(firstKey, firstValue);//放值
size = 1;
setThreshold(INITIAL_CAPACITY);//阀值16*2/3 容量的2/3大小
}
}
ThreadLocalMap明显就是一个简化版的hashmap,数据结构是Entry数组,每次2倍扩容,没有链表红黑树,其实现了自己的寻址,我想看懂这些应该是不难的。 这里也能看出Thread、ThreadLocal、ThreadLocalMap的关系
Thread存在一个ThreadLocalMap,ThreadLocalMap是一个类型Map的结构可以存储多个ThreadLocal

ThreadLocalMap与WeakReference也理解下,ThreadLocalMap内部存储单元Entry继承WeakReference,是弱引用
弱引用:如果一个对象只具有弱引用,那么垃圾回收器在扫描到该对象时,无论内存充足与否,都会回收该对象的内存。
这么做主要是为了内存回收考虑,当我们用普通线程没问题,线程用完自己会关闭释放内存,但是线程池呢,线程一直存活,是不是意味着这个Map一直存在,但是换任务了等等,其中很多的存储都会是废值,
程序执行时间长了,就可能引发OOM内存泄漏问题,特别是我们的value再比较大。因此用了弱引用,内存不够GC时会干掉key,但是value却还是存在的,而ThreadLocalMap的set、get、remove方法操作元素时会检查null
的key然后释放value,就解决这个问题。但也不绝对,如果ThreadLocal实例我们置null,那ThreadLocal就会回收,但是Map就会一直存在,也可能引发OOM。

    map.set
private void set(ThreadLocal<?> key, Object value) { // We don't use a fast path as with get() because it is at
// least as common to use set() to create new entries as
// it is to replace existing ones, in which case, a fast
// path would fail more often than not. Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (len-1); for (Entry e = tab[i];
e != null;
e = tab[i = nextIndex(i, len)]) {
ThreadLocal<?> k = e.get(); if (k == key) {
e.value = value;
return;
} if (k == null) {
replaceStaleEntry(key, value, i);//这里是替换null key的
return;
}
} tab[i] = new Entry(key, value);
int sz = ++size;
if (!cleanSomeSlots(i, sz) && sz >= threshold)//这里就是清理null key的
rehash();
}

其它没什么多的看的了

总结:需要明白Thread、ThreadLocal、ThreadLocalMap的关系。
ThreadLocalMap是线程的成员变量,不同的线程有不同的ThreadLocalMap,ThreadLocalMap中存储不同的ThreadLocal,实际简单说就是一个线程可以创建多个本地线程变量存多个值且只属于本线程。
WeakReference弱引用往往是面试中问到ThreadLocal类常会深入到的一个点,要知道怎么回事。正常场景ThreadLocal如果我们只是简单的创建,不自己置null,或者创建了ThreadLocal又不用等待操作也不会OOM,正常操作完全没什么大问题。

ThreadLocal 简单解析的更多相关文章

  1. 对 cloudwu 简单的 cstring 进行简单解析

    题外话 以前也用C写过字符串,主要应用的领域是,大字符串,文件读取方面.写的很粗暴,用的凑合着.那时候看见云风前辈的一个开源的 cstring 串. 当时简单观摩了一下,觉得挺好的.也没细看.过了较长 ...

  2. 基于DOM的XSS注入漏洞简单解析

    基于DOM的XSS注入漏洞简单解析http://automationqa.com/forum.php?mod=viewthread&tid=2956&fromuid=21

  3. 15.5 自学Zabbix之路15.5 Zabbix数据库表结构简单解析-其他 表

    点击返回:自学Zabbix之路 自学Zabbix之路15.5 Zabbix数据库表结构简单解析-其他 表  1. Actions表 actions表记录了当触发器触发时,需要采用的动作. 2.Aler ...

  4. 深度优先搜索DFS和广度优先搜索BFS简单解析(新手向)

    深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每个点仅被访问一次,这个过程就是图的遍历.图的遍历常用的有深度优先搜索和广度优先搜索,这两者对于有向图和无向图 ...

  5. List<T>集合的Sort自定义排序用法简单解析

    List<T>集合的Sort自定义排序用法简单解析: 如下:一系列无序数字,如果想要他们倒序排列,则使用如下代码: 那么如何理解这段代码呢? (x,y)表示相邻的两个对象,如果满足条件:x ...

  6. Maven项目pom.xml文件简单解析

    Maven项目pom.xml简单解析 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="h ...

  7. 自学Zabbix之路15.1 Zabbix数据库表结构简单解析-Hosts表、Hosts_groups表、Interface表

    点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix之路15.1 Zabbix数据库表结构简单解析-Hosts表.Hosts_grou ...

  8. 自学Zabbix之路15.2 Zabbix数据库表结构简单解析-Items表

    点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix之路15.2 Zabbix数据库表结构简单解析-Items表 Items表记录了i ...

  9. 自学Zabbix之路15.3 Zabbix数据库表结构简单解析-Triggers表、Applications表、 Mapplings表

    点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix之路15.3 Zabbix数据库表结构简单解析-Triggers表.Applica ...

随机推荐

  1. Fira Code:适合程序员的编程字体

    #Fira Code Fira 是 Mozilla 公司 主推的字体系列.Fira Code 是其中的一员,专为写程序而生.出来具有等宽等基本属性外,还加入了编程连字特性(ligatures). Fi ...

  2. 基于python的selenium常用操作方法(1)

    1 selenium定位方法    Selenium提供了8种定位方式. ·         id ·         name ·         class name ·         tag ...

  3. SqlServer ----- 根据查询语句创建视图

    我们都知道视图的本质就是查询语句,那么就可以根据查询语句创建视图, 前提 知道视图的组成,已经写好的sql 语句,多表或单表的查询语句,将查询语句变成视图. 所以视图可以由单表,多表或视图加表构成. ...

  4. FCN用卷积层代替FC层原因(转)

    原博客连接 : https://www.cnblogs.com/byteHuang/p/6959714.html CNN对于常见的分类任务,基本是一个鲁棒且有效的方法.例如,做物体分类的话,入门级别的 ...

  5. Awesome Java: Github上关于Java相关的工具

    Awesome Java 这是Github上关于Java相关的工具,框架等等资源集合. 原文参考: https://github.com/akullpp/awesome-java. @pdai 最全的 ...

  6. 死磕 java同步系列之CountDownLatch源码解析

  7. RocketMQ(4)---RocketMQ核心配置讲解

    RocketMQ核心配置讲解 RocketMQ的核心配置在broker.conf配置文件里,下面我们来分析下它. 一.broker.conf配置 下面只列举一些常用的核心配置讲解. 1.broker. ...

  8. PHP面试题2019年小米工程师面试题及答案解析

    一.单选题(共29题,每题5分) 1.PHP面向对象方法重写描述错误的是? A.子类必须继承父类 B.子类可以重写父类已有方法 C.重写之后子类会调用父类方法 D.子类也可以具有与父类同名的属性,进行 ...

  9. 关于Spring Boot你不得不知道的事--Spring Boot的基本操作

    1 Pom文件 1.1 spring-boot-starter-parent 表示当前pom文件从spring-boot-starter-parent继承下来,在spring-boot-starter ...

  10. 专访腾讯方亮:WeTest品牌全面升级,“好的产品一定深谙人性”

    工欲善其事,必先利其器.在当下竞争激烈的市场环境中,精品,已经成为所有游戏厂商安身立命之本.但如何提升品质,使产品成为精品,行业内却长期缺乏公开.透明,以及具备实际参考.实操价值的标准. 制定一项标准 ...