ThreadLocal 简单解析
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 简单解析的更多相关文章
- 对 cloudwu 简单的 cstring 进行简单解析
题外话 以前也用C写过字符串,主要应用的领域是,大字符串,文件读取方面.写的很粗暴,用的凑合着.那时候看见云风前辈的一个开源的 cstring 串. 当时简单观摩了一下,觉得挺好的.也没细看.过了较长 ...
- 基于DOM的XSS注入漏洞简单解析
基于DOM的XSS注入漏洞简单解析http://automationqa.com/forum.php?mod=viewthread&tid=2956&fromuid=21
- 15.5 自学Zabbix之路15.5 Zabbix数据库表结构简单解析-其他 表
点击返回:自学Zabbix之路 自学Zabbix之路15.5 Zabbix数据库表结构简单解析-其他 表 1. Actions表 actions表记录了当触发器触发时,需要采用的动作. 2.Aler ...
- 深度优先搜索DFS和广度优先搜索BFS简单解析(新手向)
深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每个点仅被访问一次,这个过程就是图的遍历.图的遍历常用的有深度优先搜索和广度优先搜索,这两者对于有向图和无向图 ...
- List<T>集合的Sort自定义排序用法简单解析
List<T>集合的Sort自定义排序用法简单解析: 如下:一系列无序数字,如果想要他们倒序排列,则使用如下代码: 那么如何理解这段代码呢? (x,y)表示相邻的两个对象,如果满足条件:x ...
- Maven项目pom.xml文件简单解析
Maven项目pom.xml简单解析 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="h ...
- 自学Zabbix之路15.1 Zabbix数据库表结构简单解析-Hosts表、Hosts_groups表、Interface表
点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix之路15.1 Zabbix数据库表结构简单解析-Hosts表.Hosts_grou ...
- 自学Zabbix之路15.2 Zabbix数据库表结构简单解析-Items表
点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix之路15.2 Zabbix数据库表结构简单解析-Items表 Items表记录了i ...
- 自学Zabbix之路15.3 Zabbix数据库表结构简单解析-Triggers表、Applications表、 Mapplings表
点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix之路15.3 Zabbix数据库表结构简单解析-Triggers表.Applica ...
随机推荐
- Python爬虫教程-使用chardet
Spider-03-使用chardet继续学习python爬虫,我们经常出现解码问题,因为所有的页面编码都不统一,我们使用chardet检测页面的编码,尽可能的减少编码问题的出现 网页编码问题解决使用 ...
- C语言程序设计100例之(3): Cantor表
例3 Cantor表 题目描述 现代数学的著名证明之一是Georg Cantor证明了有理数是可枚举的.他是用下面这一张表来证明这一命题的: 1/1 1/2 1/3 1/4 …… 2/1 ...
- 支付签名 MD5Util 排序工具类
package com.skynet.wechat.wxPay.common; import java.security.MessageDigest; import java.util.Iterato ...
- 制作windows安装包的工具
https://nsis.sourceforge.io/Download https://www.installaware.com/ https://www.advancedinstaller.com ...
- MySQL 表和列的注释
像代码一样,可以为表以及表中的列添加注释,方便其他人知晓其功能.对于一些字段,在经过一定时间后,创建者未必也能想起其具体的含意,所以注释显得尤为重要. 注释的添加 注释的添加是通过在定义表或列的时候在 ...
- 最近的项目系之2——core3.0整合Autofac
1.前言 core3.0与之前版本相比,有一些brokenchanges,那周边一些配套组件往往也难逃brokenchanges,Autofac也不例外.这里重点关注core整合Autofac,与之前 ...
- python基础(30):黏包、socket的其他方法
1. 黏包 1.1 黏包现象 让我们基于tcp先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd) 同时执行多条命令之后,得到的结果很可能只有一部分,在执行其他命令的时候又接 ...
- 测试工程师技术tree(“自言自语”)
理论部分 1.测试分为哪几个阶段 2.测试的流程是什么 3.如何做好测试计划 4.常见的测试用例设计方法有哪些 5.一条bug记录包含哪些内容 5.如何分层自动化测试 6.如何保证脚本的有效性 7.如 ...
- SQL 带有output、inserted、deleted
因需求的关系需要将修改的值返回,故查了些资料发现了OUTPUT这个好东西,现记录下来以防以后忘记 使用例子: 1.对于INSERT,可以引用inserted表以查询新行的属性. insert i ...
- RPM包安装——手动安装
RPM包安装 手动安装 挂载光盘 首先查看光盘是否挂载(使用mount命令) RPM包存放位置 在你光盘挂载点的Packages目录下 使用 ll | grep 关键字 可以快速找到你想要的RPM包 ...