ThreadLocal源码调试——“this”作为key
前言:在一次面试过程中被问到ThreadLocal,大家都知道ThreadLocal可以为每个线程单独提供一个副本,从而实现变量间的隔离。在ThreadLocal中set和get操作的key是什么,ThreadLocal又是怎样实现各线程间互不干扰的,本文通过调试ThreadLocal的源码来阐述这些问题。
注:jdk版本:jdk1.7.0_51
1.set与get源码
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
下面通过对源码的调试说明具体流程。
2.具体调试过程
public class CodeTest02
{
public static void main(String[] args) throws InterruptedException
{
final ThreadLocal<Integer> threadLocal = new ThreadLocal<>(); Thread t1 = new Thread(new Runnable()
{
@Override
public void run()
{
threadLocal.set(1); System.out.println(threadLocal.get());
}
},"t1");
t1.start(); t1.join();
threadLocal.set(2); System.out.println(threadLocal.get()); } }
说明:在主线程和t1线程中进行set操作,最后输出如下:
从输出结果可以看出两个线程间的值互不影响。
具体调试过程:
注意:当前threadLocal的地址值为ThreadLocal@430。进入断点,如下图所示。
注意:
1)this的值为当前ThreadLocal对象的值(ThreadLocal@430)。
2)t表示当前线程t1。
3)map为空,注意这里的map为ThreadLocalMap。
转入createMap函数,传入的值为当前线程t1和value(value=1)。
说明:
1)createMap函数会为t1线程创建一个ThreadLocalMap。
从注释中可以看出,ThreadLocal为线程的附属值,所以ThreadLocalMap也为线程的一个附属属性,它被ThreadLocal维护。
2)该ThreadLocalMap的键为this,从调试信息中可以看出this的值为ThreadLocal@430。
接下来看get函数:
说明:
1)通过t1线程,取出ThreadLocalMap,这里获取set中根据t1创建的threadLocals对象。
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
2)在ThreadLocalMap中根据this,也就是当前ThreadLocal@430,取得设置的值。
总结:
1)ThreadLocal中在set操作时,key为当前ThreadLocal对象。
2)ThreadLocal会为每个线程都创建一个ThreadLocalMap,对应程序中的t.threadLocals = new ThreadLocalMap(this, firstValue),ThreadLocalMap为当前线程的属性。
3)通过对每个线程创建一个ThreadLocalMap实现本地副本。当取值时,实际上就是通过key在map中取值,当然此时的key为ThreadLocal对象,而map为每个线程独有的map,从而实现变量的互不干扰。
by Shawn Chen,2018.6.2日,下午。
ThreadLocal源码调试——“this”作为key的更多相关文章
- Java多线程9:ThreadLocal源码剖析
ThreadLocal源码剖析 ThreadLocal其实比较简单,因为类里就三个public方法:set(T value).get().remove().先剖析源码清楚地知道ThreadLocal是 ...
- Java多线程学习之ThreadLocal源码分析
0.概述 ThreadLocal,即线程本地变量,是一个以ThreadLocal对象为键.任意对象为值的存储结构.它可以将变量绑定到特定的线程上,使每个线程都拥有改变量的一个拷贝,各线程相同变量间互不 ...
- Java并发编程之ThreadLocal源码分析
## 1 一句话概括ThreadLocal<font face="微软雅黑" size=4> 什么是ThreadLocal?顾名思义:线程本地变量,它为每个使用该对象 ...
- ThreadLocal源码解读
1. 背景 ThreadLocal源码解读,网上面早已经泛滥了,大多比较浅,甚至有的连基本原理都说的很有问题,包括百度搜索出来的第一篇高访问量博文,说ThreadLocal内部有个map,键为线程对象 ...
- 并发编程(四)—— ThreadLocal源码分析及内存泄露预防
今天我们一起探讨下ThreadLocal的实现原理和源码分析.首先,本文先谈一下对ThreadLocal的理解,然后根据ThreadLocal类的源码分析了其实现原理和使用需要注意的地方,最后给出了两 ...
- SpringBoot自动配置源码调试
之前对SpringBoot的自动配置原理进行了较为详细的介绍(https://www.cnblogs.com/stm32stm32/p/10560933.html),接下来就对自动配置进行源码调试,探 ...
- HashMap源码调试——认识"put"操作
前言:通常大家都知道HashMap的底层数据结构为数组加链表的形式,但其put操作具体是怎样执行的呢,本文通过调试HashMap的源码来阐述这一问题. 注:jdk版本:jdk1.7.0_51 1.pu ...
- ThreadLocal详解,ThreadLocal源码分析,ThreadLocal图解
本文脉路: 概念阐释 ----> 原理图解 ------> 源码分析 ------> 思路整理 ----> 其他补充. 一.概念阐述. ThreadLocal 是一个为 ...
- 【JAVA】ThreadLocal源码分析
ThreadLocal内部是用一张哈希表来存储: static class ThreadLocalMap { static class Entry extends WeakReference<T ...
随机推荐
- Asp.net 获取访问者IP
using System.Web; namespace Wxlhjcyy.Public { public class GetIp { public static string IPAddress { ...
- Asp.Net MVC中Action跳转(转载)
首先action的跳转大致归类: 1跳转到与当前同一控制器内的action和不同控制器内的action. 2带有参数的action跳转和不带参数的action跳转. 3跳转到指定视图,不经过Contr ...
- [Linux] 简单安装和使用composer
wget https://getcomposer.org/installer //下载一个脚本文件 php installer //php执行下这个php脚本 mv composer.phar /us ...
- $_POST和$GLOBALS['HTTP_RAW_POST_DATA'] 的区别
HTTP 协议是建立在 TCP/IP 协议之上的应用层规范,它把 HTTP 请求分为三个部分:请求行.请求头.消息主体.协议规定 POST 提交的数据必须放在消息主体(entity-body)中,但协 ...
- String为什么是不可变的?
前几天一个面试被问到String为什么是不可变的?, 自我感觉当时回答的不太理想, 事后总结一下 不可变的是什么 我们谈论的String不可变, 指的是字符串的值不可变 例: String s = & ...
- Java高并发 -- 并发扩展
Java高并发 -- 并发扩展 主要是学习慕课网实战视频<Java并发编程入门与高并发面试>的笔记 死锁 死锁是指两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象, ...
- 全网最贴心webpack系列教程和配套代码
webpack-demos:全网最贴心 webpack 系列教程和配套代码 欢迎关注个人技术博客:godbmw.com.每周 1 篇原创技术分享!开源教程(webpack.设计模式).面试刷题(偏前端 ...
- Aurelia binding
今天介绍一下使用Aurelia binding 模块绑定HTML属性/事件的方式.我们依然使用之前创建的代码例子. Aurelia binding 绑定属性或者方法的通用模式就是 XXX.comman ...
- 输出映射resultType
√1:简单类型 √2:简单类型列表 √3:POJO类型只有列名或列名的别名与POJO的属性名一致,该列才可以映射成功只要列名或列名的别名与POJO的属性名有一个一致,就会创建POJO对象如果列名或列名 ...
- linux开启新端口
1.使用vi或者vim打开iptables配置文件: vi /etc/sysconfig/iptables 2.在编辑页面新增加信任端口: -A INPUT -m state --state NEW ...