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源码学习的更多相关文章

  1. java Integer 源码学习

    转载自http://www.hollischuang.com/archives/1058 Integer 类在对象中包装了一个基本类型 int 的值.Integer 类型的对象包含一个 int 类型的 ...

  2. ThreadLocal源码学习笔记

    系列文章目录和关于我 一丶ThreadLocal结构 每一个Thread对象都有一个名为threadLocals类型为ThreadLocal.ThreadLocalMap的属性,ThreadLocal ...

  3. Java集合源码学习(一)集合框架概览

    >>集合框架 Java集合框架包含了大部分Java开发中用到的数据结构,主要包括List列表.Set集合.Map映射.迭代器(Iterator.Enumeration).工具类(Array ...

  4. Java集合源码学习(三)LinkedList分析

    前面学习了ArrayList的源码,数组是顺序存储结构,存储区间是连续的,占用内存严重,故空间复杂度很大.但数组的二分查找时间复杂度小,为O(1),数组的特点是寻址容易,插入和删除困难.今天学习另外的 ...

  5. java BigInteger源码学习

    转载自http://www.hollischuang.com/archives/176 在java中,有很多基本数据类型我们可以直接使用,比如用于表示浮点型的float.double,用于表示字符型的 ...

  6. Java集合源码学习(三)LinkedList

    前面学习了ArrayList的源码,数组是顺序存储结构,存储区间是连续的,占用内存严重,故空间复杂度很大.但数组的二分查找时间复杂度小,为O(1),数组的特点是寻址容易,插入和删除困难.今天学习另外的 ...

  7. Java集合源码学习(五)几种常用集合类的比较

    这篇笔记对几个常用的集合实现,从效率,线程安全和应用场景进行综合比较. >>ArrayList.LinkedList与Vector的对比 (1)相同和不同都实现了List接口,使用类似.V ...

  8. Java集合源码学习(四)HashMap分析

    ArrayList.LinkedList和HashMap的源码是一起看的,横向对比吧,感觉对这三种数据结构的理解加深了很多. >>数组.链表和哈希表结构 数据结构中有数组和链表来实现对数据 ...

  9. Java集合源码学习(二)ArrayList分析

    >>关于ArrayList ArrayList直接继承AbstractList,实现了List. RandomAccess.Cloneable.Serializable接口,为什么叫&qu ...

随机推荐

  1. centos6.5部署gitlab

    安装过程参考: https://www.cnblogs.com/wenwei-blog/p/5861450.html https://ehlxr.me/2016/07/31/CentOS-%E7%B3 ...

  2. Tomcat学习(一)------部署Web应用方法总结

    Tomcat部署Web应用方法总结 在Tomcat中部署Java Web应用程序有两种方式:静态部署和动态部署. 在下文中$CATALINA_HOME指的是Tomcat根目录. 一.静态部署 静态部署 ...

  3. JDBC多表操作

    一.一对多关系:部门管理系统 1.数据库 create table department ( id ) primary key, name ) ); create table employee ( i ...

  4. Fiddler抓包原来可以这么玩

    Fiddler是一个抓包工具 1 解压压缩包至C\program files (x86) 2 打开C program files (x86) Fiddler Web Debugger V4.6.201 ...

  5. Socket之简单的Unity3D聊天室__TCP协议

    服务器端程序 using System; using System.Collections.Generic; using System.Linq; using System.Net; using Sy ...

  6. OpenGL学习笔记(1) 画一个三角形

    最近找实习有一丢丢蛋疼,沉迷鬼泣5,四周目通关,又不想写代码,写篇笔记复习一下,要好好学图形学啊 用OpenGL画一个三角形 项目的简介 记录一下跟着learnOpenGL学习的过程 笔记里的代码放在 ...

  7. alibaba/canal 阿里巴巴 mysql 数据库 binlog 增量订阅&消费组件

    基于日志增量订阅&消费支持的业务: 数据库镜像 数据库实时备份 多级索引 (卖家和买家各自分库索引) search build 业务cache刷新 价格变化等重要业务消息 项目介绍 名称:ca ...

  8. Java字符串连接操作的性能问题

    首先,看一段实验程序: package com.test; class StringTest { public static void main(String[] args) { long start ...

  9. 火狐插件安装-基于web自动化测试

    一.Firebug 安装 1.  打开火狐浏览器—选择右上角“打开菜单”(图一)----附件组件(图二) 图一 图二 2.  点击:扩展(图三)—-------用于所有附加组件的工具(图四)----选 ...

  10. 基于Python的信用评分卡模型分析(一)

    信用风险计量体系包括主体评级模型和债项评级两部分.主体评级和债项评级均有一系列评级模型组成,其中主体评级模型可用“四张卡”来表示,分别是A卡.B卡.C卡和F卡:债项评级模型通常按照主体的融资用途,分为 ...