当前位置: 首页 > 编程日记 > 正文

ThreadLocal源码分析

ThreadLocal的作用

Java对象是线程间共享的,但有时我们需要一些线程间隔离的对象,该对象只能由同一个线程读写,对其他线程不可见。ThreadLocal正式提供了这样的机制,详细使用方式请参考Java ThreadLocal。

ThreadLocal实现原理

自定义实现

在没有看源码前,如果我自己实现一个ThreadLocal,可能是这样的

public class ThreadLocal<T> {private Map<Thread, T> values = new WeakHashMap<Thread, T>();public synchronized void set(T value) {values.put(Thread.currentThread(), value);}public synchronized T get() {return values.get(Thread.currentThread());}
}

JDK实现

Java源码中ThreadLocal的核心代码如下:

public class ThreadLocal<T> {public T get() {Thread t = Thread.currentThread();//从当前的Thread对象中取出ThreadLocalMap成员,key是ThreadLocal,value是set的值。ThreadLocalMap map = getMap(t);if (map != null) {ThreadLocalMap.Entry e = map.getEntry(this);if (e != null)return (T)e.value;}return setInitialValue();}public void set(T value) {Thread t = Thread.currentThread();//从当前的Thread对象中取出ThreadLocalMap成员,key是ThreadLocal,value是set的值。ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);}ThreadLocalMap getMap(Thread t) {return t.threadLocals;}}//threadLocals变量存放在Thread对象中
public class Thread{/* ThreadLocal values pertaining to this thread. This map is maintained* by the ThreadLocal class. */ThreadLocal.ThreadLocalMap threadLocals = null;/** InheritableThreadLocal values pertaining to this thread. This map is* maintained by the InheritableThreadLocal class.*/ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;...
}

不同于自定义实现,源码中ThreadLocal.set(T value)的值是由Thread对象来缓存的。那么问题就来了?

1. 为什么ThreadLocal.set(T value)的值由Thread对象来缓存,为什么不像自定义实现那样放在ThreadLocal中?

我理解主要是性能考虑。如果放在ThreadLocal中,由于多线程操作同一个Map对象,将不得不加锁保护。而将value直接放在Thread对象中,不同的线程有各自的Thread对象,因此也就无需加锁。因此将value放在Thread对象中性能会好一些。大家如果有不同的见解,请指教^_^

2. 既然value存放在Thread中,为什么不直接由Thread提供getter/setter接口,而需要额外有一个ThreadLocal类?

我理解此处的value虽然和Thread之间存在映射关系,但是不属于Thread的属性,放在ThreadLocal更多是性能上的考虑,因此由Thread提供getter/setter并不适合。

InheritableThreadLocal原理

InheritableThreadLocal中存放的value是当前线程和当前线程创建出来的子线程可见的。其核心源码如下。

public class Thread {private void init(ThreadGroup g, Runnable target, String name,long stackSize) {...Thread parent = currentThread();...//将parent的inheritableThreadLocals同步到childif (parent.inheritableThreadLocals != null)this.inheritableThreadLocals =//此处create一个新的ThreadLocalMap对象ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);...}

由于child.inheritableThreadLocals是新创建的ThreadLocalMap对象,因此在child中再次执行set,不会影响parent。

参考文献

  1. Java ThreadLocal http://tutorials.jenkov.com/java-concurrency/threadlocal.html

相关文章:

远程连接windows出现身份验证错误,提示由于CredSSP加密Oracle修正解决方案

本机操作系统(OS版本:10.0.17134) 远程计算机操作系统&#xff08;OS版本:6.3.9600&#xff09; 远程连接的时候报错“出现身份验证错误&#xff0c;要求的函数不受支持。远程计算机:xxx 这可能是由于CredSSP加密Oracle修正,若要了解详细信息...” 原因是系统更新安装了补丁&am…

MediaWiki安装

MediaWiki可以方便的让你搭建自己的wiki&#xff0c;公司内部使用非常方便官网&#xff1a; https://www.mediawiki.org/wiki/MediaWiki安装MediaWiki的必要环境 PHPMysql 下载最新版解压即可 # tar -xzvf mediawiki-1.25.2.tar.gz # mv mediawiki-1.25.2 wiki 输入首页引导一…

sql的四种连接 用mysql的语句写_170221、浅谈mysql的SQL的四种连接

例子&#xff1a;-------------------------------------------------a表 id name b表 id job parent_id1 张3 1 23 12 李四 2 34 23 王武 3 34 4a.id同parent_id 存在关…

MySQL冷备份的跨操作系统还原

数据来源&#xff1a;linux平台mysql版本为5.7 数据去向&#xff1a;windows平台mysql版本为5.7 操作步骤&#xff1a; 第一步&#xff1a;关闭mysql服务 service mysqld stop 第二步&#xff1a;归档linux平台下mysql的数据目录 tar -czvf data.tar.gz /usr/local/mysql/data …

Java 社区领袖联合发文:别慌,Java 仍然是免费的!

开发四年只会写业务代码&#xff0c;分布式高并发都不会还做程序员&#xff1f; >>> 在去年的 Java One 上&#xff0c;Mark Cavage 当时宣布 Oracle 将逐步开源 Oracle JDK 的专有功能&#xff08;商业特性&#xff09;。Oracle Java 平台产品管理高级总监 Donald …

Squid安装

最新版Squid安装 http://www.squid-cache.org/Versions/v3/3.5/# wget http://www.squid-cache.org/Versions/v3/3.5/squid-3.5.7.tar.gz# tar zxvf squid-3.5.7.tar.gz# cd squid-3.5.7# ./configure --prefix/usr/local/squid# make && make install# chmod -R 777 /…

Java内部类手机专卖店_JAVA——内部类的那些事儿

obj3.func();//3.2 访问静态内部类的静态方法(通过类名访问)Outer.StaInner.staFunc();//4 局部内部类访问局部变量Outer obj4 new Outer();obj4.local();//5 匿名内部类Outer obj5 new Outer();obj5.anonymous();//6 匿名内部类作为参数asPara(new AbstractClass() {public …

Linux下Postfix的配置和使用

Postfix为何物&#xff0c;详见&#xff1a;http://zh.wikipedia.org/wiki/Postfix 0.关于Postfix postfix的产生是为了替代传统的sendmail.相较于sendmail,postfix在速度。性能和稳定性上都更胜一筹。如今眼下许多的主流邮件服务事实上都在採用postfix. 当我们须要一个轻量级的…

部分人说 Java 的性能已经达到甚至超过 C++,是真的吗?

好多Java程序员都说由于JIT技术的引入&#xff0c;Java的性能已经和C一样了&#xff0c;而且Java的开发效率极高&#xff0c;可以省下60%的时间。请问事实真的是这样吗&#xff1f;我平常也都在写这两个语言&#xff0c;但是因为开发的软件的复杂度不大&#xff0c;并没有感觉到…

Wiki 开源软件

Wiki 是一个协同著作平台或称开放编辑系统。所谓协同工作&#xff0c; 即它能够让浏览网页的人都能够去修订网页&#xff0c;其简介的 ... Wiki 是怎么做到的. Wiki 使用 了简化的语法&#xff0c;替代复杂的HTML&#xff0c;加上WEB 界面的编辑工具&#xff0c;降低内容维护的…

Android studio安装与调试

1.下载安装android studio 下载好之后安装好2.启动报错提示1&#xff09;进入刚安装的Android Studio目录下的bin目录。找到idea.properties文件&#xff0c;用文本编辑器打开。2&#xff09;在idea.properties文件末尾添加一行&#xff1a; disable.android.first.runtrue &am…

java的父类java.lang.object_根父类:java.lang.Object

1、根父类(1)Object类型是所有引用数据类型的超类&#xff0c;包括数组类型如果一个类没有显式的声明它的父类&#xff0c;那么它的父类就是Object。(2)Object类中的方法&#xff0c;会继承到所有类型的对象中&#xff0c;包括数组对象。即所有对象都可以调用Object类中声明的方…

spring cloud服务发现注解之@EnableDiscoveryClient与@EnableEurekaClient

在使用服务发现的时候提到了两种注解&#xff0c;一种为EnableDiscoveryClient,一种为EnableEurekaClient,用法上基本一致&#xff0c;今天就来讲下两者&#xff0c;下文是从stackoverflow上面找到的对这两者的解释&#xff1a;原文链接 There are multiple implementations of…

strust2自定义interceptor的基本方法及操作

需求&#xff1a;制作一个网站需要用户登陆后才能查看&#xff0c;即一个权限的问题 1.首先明确在用户没登陆前有两个Action请求是可以通过的&#xff0c;即注册和登陆。 2.创建拦截器&#xff0c;如UserLoginInterceptor.java&#xff0c;如下 public class UserLoginIntercep…

使用xdebug分析thinkphp框架函数调用图

开发中需要性能调优&#xff0c;使用xdebug分析thinkphp框架函数调用图。关于xdebug的安装参考这2篇 NetBeans配置Xdebug 远程调试PHP php扩展xdebug安装以及用kcachegrind系统分析1.安装xdebug 需要先去http://www.xdebug.org看看一些文档&#xff0c;xdebug作为php扩展安装 #…

java+script+当前日期_如何在JavaScript中获取当前日期?

如何在JavaScript中获取当前日期&#xff1f;#1楼您可以使用扩展了 Date对象的Date.js库&#xff0c;从而可以使用.today()方法。#2楼如果您想对日期格式进行更多的粒度控制&#xff0c;我强烈建议您查看一下momentjs。 很棒的图书馆-只有5KB。 http://momentjs.com/#3楼你可以…

java中的类修饰符、成员变量修饰符、方法修饰符。

类修饰符&#xff1a; public&#xff08;访问控制符&#xff09;&#xff0c;将一个类声明为公共类&#xff0c;他可以被任何对象访问&#xff0c;一个程序的主类必须是公共类。 abstract&#xff0c;将一个类声明为抽象类&#xff0c;没有实现的方法&#xff0c;需要子类提供…

Linux 系统挂载数据盘

Linux 系统挂载数据盘&#xff1a; 适用系统&#xff1a;Linux&#xff08;Redhat , CentOS&#xff0c;Debian&#xff0c;Ubuntu&#xff09;* Linux的云服务器数据盘未做分区和格式化&#xff0c;可以根据以下步骤进行分区以及格式化操作。下面的操作将会把数据盘划分为一个…

java 启动某个类_java – Spring Boot – 如何指定备用启动类? (多个入口点)

我想添加一个替代的入口点到我的Spring-Boot应用程序.我宁愿把它当成一个肥罐.这可能吗&#xff1f;根据他们的documentation,属性loader.main指定要启动的主类的名称.我尝试java -jar MyJar.jar –loader.main com.mycompany.AlternateMain,但是我的pom.xml中指定的start-cla…

WIN7 64位系统下,右下角的声音和电源图标不见的解决办法

近日&#xff0c;电脑突然出现任务栏右下角的声音和电源图标消失不见的问题&#xff0c;重启仍旧没有修复&#xff0c;后来找到了解决办法 解决办法&#xff1a; 1.CtrlShiftEsc键调出windows资源管理器。 2.找到进程中的explorer.exe进程并结束它。 3.在文件选项的新建任务选项…

创建Maven版Java工程

步骤&#xff1a; 创建成功后&#xff0c;如图&#xff1a; 转载于:https://www.cnblogs.com/zhzcode/p/9722902.html

Linux系统启动任务的写法

1.到/etc/rc.d目录# cd /etc/rc.d 2.修改rc.local # vim ./rc.local你之前是怎么启动nginx和php命令复制即可。例如&#xff1a;/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf/etc/init.d/php-fpm3.一定要给权限 # chmod x rc.local特别是喜欢下载到本地修…

java ee不能运行_Java9+移除 Java EE,导致我的 groovy 脚本无法运行

以以下这段代码为例Grab(org.jsoup:jsoup:1.10.1)import org.jsoup.JsoupJsoup.connect(https://v2ex.com).get().select(span.item_title > a).each {println it.text() : https://v2ex.com it.attr(href)}原本是 groovy2.5java8&#xff0c;可以正常跑&#xff0c;然后…

虚拟文件系统(VFS)

原文链接&#xff1a;http://www.orlion.ga/1008/ linux在不同的文件系统之上做了一个抽象层&#xff0c;使得文件、目录、读写访问等概念都成为抽象层概念&#xff0c;这个抽象层被称为虚拟文件系统(VFS)。 linux内核的VFS子系统如下: 每个进程在PCB(Process Control Block)中…

[学习笔记]矩阵乘法及其优化dp

1.定义&#xff1a; $c[i][j]\sum a[i][k]\times b[k][j]$ 所以矩阵乘法有条件&#xff0c;(n*m)*(m*p)n*p 即第一个矩阵的列数等于第二个矩阵的行数&#xff0c;否则没有意义。 2.结合律与分配率 矩阵乘法不一定任何时候都有交换律。因为交换后甚至不能保证第一个矩阵的列数等…

[LeetCode] Longest Substring with At Most K Distinct Characters 最多有K个不同字符的最长子串...

Given a string, find the length of the longest substring T that contains at most k distinct characters. For example, Given s “eceba” and k 2, T is "ece" which its length is 3. 这道题是之前那道Longest Substring with At Most Two Distinct Charac…

Linux创建指定用户特定指定目录权限

指定用户特定指定目录权限需要注意要指定好文件夹的权限&#xff0c;不然会导致nginx不能访问&#xff0c;最好是在root下建立目录&#xff0c;然后 # useradd -d /usr/www -m tempuser# passwd tempuser 回车输入密码 注意一定要带用户名&#xff0c;不然就是修改root!!!# c…

python asyncio教程_python中使用asyncio实现异步IO实例分析

1、说明Python实现异步IO非常简单&#xff0c;asyncio是Python 3.4版本引入的标准库&#xff0c;直接内置了对异步IO的支持。asyncio的编程模型就是一个消息循环。我们从asyncio模块中直接获取一个EventLoop的引用&#xff0c;然后把需要执行的协程扔到EventLoop中执行&#xf…

c语言初学 循环 的灵活使用小案例

上为流程图 上为代码实现&#xff0c;没有做优化。接下来是效果图。 时间2018.10.01 地点&#xff1a;广东轻工业职业技术学院复制代码 转载于:https://juejin.im/post/5bb1d98a5188255c9a77441a

常见maven引用

json-lib Could not find artifact net.sf.json-lib:json-lib:jar json-lib是需要区分jdk版本的&#xff0c;pom.xml中的配置应加上<classifier>标签&#xff0c;如用jdk15&#xff1a; <dependency><groupId>net.sf.json-lib</groupId><artifactId…