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. springboot+lucene实现公众号关键词回复智能问答

    一.场景简介 最近在做公众号关键词回复方面的智能问答相关功能,发现用户输入提问内容和我们运营配置的关键词匹配回复率极低,原因是我们采用的是数据库的Like匹配. 这种模糊匹配首先不是很智能,而且也没有 ...

  2. Jupyter notebook 使用

    1. 安装代码自动补全 需安装 nbextensions 插件,网站:https://jupyter-contrib-nbextensions.readthedocs.io/en/latest/ins ...

  3. js 元素自动点击/执行问题

    a标签对于一下两种方式是无效的: <a href="http://qq.com">QQ</a> $('.obj').click(); $('.obj').t ...

  4. Linux进程和计划任务实践

    1.显示统计占用系统内存最多的进程,并排序. 方法一 [root@test ~]#ps aux --sort=%mem USER PID %CPU %MEM VSZ RSS TTY STAT STAR ...

  5. Python远程linux执行命令

    1.远程登录到linux上,使用到的模块paramiko #远程登陆操作系统 def ssh(sys_ip,username,password,cmds): try #创建ssh客户端 client ...

  6. 测试工程师技术tree(“自言自语”)

    理论部分 1.测试分为哪几个阶段 2.测试的流程是什么 3.如何做好测试计划 4.常见的测试用例设计方法有哪些 5.一条bug记录包含哪些内容 5.如何分层自动化测试 6.如何保证脚本的有效性 7.如 ...

  7. 用vue和layui简单写一个响应式数据展示表

    在创建项目之前,先把我们需要的文件打包处理 <!DOCTYPE html> <html lang="en"> <head> <meta c ...

  8. ABP进阶教程4 - 分页排序

    点这里进入ABP进阶教程目录 下载插件 打开Datatables官网(https://datatables.net/download/) 下载插件,复制到JD.CRS.Web.Mvc\wwwroot\ ...

  9. 【JavaWeb】EL表达式

    EL表达式 EL表达式语言,用于简化JSP的输出: EL表达式的基本语法:${表达式}: 示例:<h1>学生姓名:${student.name}</h1> 作用域对象 忽略书写 ...

  10. React Hooks究竟是什么呢?

    摘要: React Hooks原理解析. 原文:快速了解 React Hooks 原理 译者:前端小智 我们大部分 React 类组件可以保存状态,而函数组件不能? 并且类组件具有生命周期,而函数组件 ...