[细品java]ThreadLocal源码学习
ThreadLocal是线程局部变量,其中保存了特定于该线程的值.每个线程都拥有一份独立的副本值,即每个线程修改变量值不影响其他线程该变量的副本值.这些特定于线程的值保存在Thread对象中,当线程终止后,这些值会作为垃圾回收.
如果没有看源码可能会认为ThreadLocal内部的实现方式应该是采用Map容器,保存一个<Thread,T>的映射关系.然而JDK内部并不是这么实现的,而是在Thread类中加入了一个散列表(ThreadLocalMap是ThreadLocal的静态内部类)来维护当前线程的所有局部变量值(即当前线程中的所有ThreadLocal变量),通过散列表数据结构可以快速地执行get和set操作.
散列
每次创建的ThreadLocal都有唯一的hashCode值,根据这个值hashCode可以计算变量在散列表中对应的地址.ThreadLocalMap的hash函数方法是将hashCode值和散列表容量大小进行与操作得到变量对应的位置.
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
冲突解决
在散列表中会存在地址冲突问题,即对于不同的hashCode可能会计算得到相同地址.对于这种情况,ThreadLocalMap采用了最简单的冲突解决方案---从冲突发生的地址d开始,依次探测d的下一个地址,直到找到一个空闲单元为止.
装填因子
ThreadLocalMap 设置的装填因子为2/3,当变量个数大于2/3时扩大容器容量再散列.
get和set
ThreadLocal的定义和使用比较简单,只要声明一个ThreadLocal变量,那该变量就为每个线程都分配了一个副本.通过set和get方法设置和获取该线程局部变量值:
ThreadLocal<Integer> integerLocal = new ThreadLocal<Integer>();
integerLocal.set(1);
Integer i = integerLocal.get();
对于以上的set和get方法的实现思路也比较简单.在set方法中,首先查看当前线程是否初始化了散列表,如果没有则创建一个散列表(初始化容器大小为16).如果存在则根据hashCode计算变量在散列表的地址并设置值.
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
get方法和set方法相似,如果散列表不存在时则创建一个散列表并设置初始值.
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();
}
[细品java]ThreadLocal源码学习的更多相关文章
- java Integer 源码学习
转载自http://www.hollischuang.com/archives/1058 Integer 类在对象中包装了一个基本类型 int 的值.Integer 类型的对象包含一个 int 类型的 ...
- ThreadLocal源码学习笔记
系列文章目录和关于我 一丶ThreadLocal结构 每一个Thread对象都有一个名为threadLocals类型为ThreadLocal.ThreadLocalMap的属性,ThreadLocal ...
- Java集合源码学习(一)集合框架概览
>>集合框架 Java集合框架包含了大部分Java开发中用到的数据结构,主要包括List列表.Set集合.Map映射.迭代器(Iterator.Enumeration).工具类(Array ...
- Java集合源码学习(三)LinkedList分析
前面学习了ArrayList的源码,数组是顺序存储结构,存储区间是连续的,占用内存严重,故空间复杂度很大.但数组的二分查找时间复杂度小,为O(1),数组的特点是寻址容易,插入和删除困难.今天学习另外的 ...
- java BigInteger源码学习
转载自http://www.hollischuang.com/archives/176 在java中,有很多基本数据类型我们可以直接使用,比如用于表示浮点型的float.double,用于表示字符型的 ...
- Java集合源码学习(三)LinkedList
前面学习了ArrayList的源码,数组是顺序存储结构,存储区间是连续的,占用内存严重,故空间复杂度很大.但数组的二分查找时间复杂度小,为O(1),数组的特点是寻址容易,插入和删除困难.今天学习另外的 ...
- Java集合源码学习(五)几种常用集合类的比较
这篇笔记对几个常用的集合实现,从效率,线程安全和应用场景进行综合比较. >>ArrayList.LinkedList与Vector的对比 (1)相同和不同都实现了List接口,使用类似.V ...
- Java集合源码学习(四)HashMap分析
ArrayList.LinkedList和HashMap的源码是一起看的,横向对比吧,感觉对这三种数据结构的理解加深了很多. >>数组.链表和哈希表结构 数据结构中有数组和链表来实现对数据 ...
- Java集合源码学习(二)ArrayList分析
>>关于ArrayList ArrayList直接继承AbstractList,实现了List. RandomAccess.Cloneable.Serializable接口,为什么叫&qu ...
随机推荐
- Oracle保存带&的数据
在SQL*Plus中默认的"&"表示替代变量,也就是说,只要在命令中出现该符号,SQL*Plus就会要你输入替代值.这就意味着你无法将一个含有该符号的字符串输入数据库或赋给 ...
- 在ns2.35下完成柯老师lab18实验
说明:柯志亨老师<ns2仿真实验-----多媒体和无线网络通信>这本书lab18实验为“无线网络封包传输遗失模型”的实验.该无线传输遗失模型是柯老师自己开发的,原始的ns-allinone ...
- jquery validate 使用示例
var el = { $jsFrom: $('.js-form'), }; // 检测用户名是否存在 jQuery.validator.addMethod("isexist", f ...
- 约束3:default约束
默认值约束(Default约束)的作用是在执行insert命令时,如果命令没有显式给指定的列赋值,那么把默认约束值插入到该列中:如果在Insert命令中显式为指定的列赋值,那么将该列插入用户显式指定的 ...
- 微服务介绍及Asp.net Core实战项目系列
0.目录 整体架构目录:ASP.NET Core分布式项目实战-目录 二.目录 0.微服务介绍 1.RESTful API 规范介绍 2.asp.net core介绍及swagger使用 3.asp. ...
- 16节实用性爆棚的Ps课:零基础秒上手,让你省钱也赚钱
ps视频教程,ps自学视频教程.ps免费视频教程下载,16节实用性爆棚的Ps课教程视频内容较大,分为俩部分: 16节实用性爆棚的Ps课第一部分:百度网盘,https://pan.baidu.com/s ...
- Bitcoin区块链攻击方式
目录 重放攻击-- 非人为攻击 其他攻击 重放攻击-- 非人为攻击 重放攻击 Replay Attach 攻击者重复发送相同的数据库包到目的主机,用以欺骗系统 用支付宝付款信息重复项商家索取商品 比特 ...
- gradle springboot 项目运行的三种方式
一.java -jar 二.eclipse中 Java Application 三.命令行 gradle bootRun
- Arthas Alibaba 开源 Java 诊断工具
Arthas 用户文档 English Docs Arthas(阿尔萨斯) 能为你做什么? Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱. 当你遇到以下类似问题而束手无策时,A ...
- day23 正则,re模块
一. 简谈正则表达式 元字符 . 除了换行符外任意字符. \w 数字.字母.下划线 \s 空白符 \b 单词的末尾 \d 数字 \n 匹配换行符 \t 匹配制表符 \W 除了数字. 字母 下划线 \D ...