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。
参考文献
- Java ThreadLocal http://tutorials.jenkov.com/java-concurrency/threadlocal.html
相关文章:

远程连接windows出现身份验证错误,提示由于CredSSP加密Oracle修正解决方案
本机操作系统(OS版本:10.0.17134) 远程计算机操作系统(OS版本:6.3.9600) 远程连接的时候报错“出现身份验证错误,要求的函数不受支持。远程计算机:xxx 这可能是由于CredSSP加密Oracle修正,若要了解详细信息...” 原因是系统更新安装了补丁&am…
MediaWiki安装
MediaWiki可以方便的让你搭建自己的wiki,公司内部使用非常方便官网: 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的四种连接
例子:-------------------------------------------------a表 id name b表 id job parent_id1 张3 1 23 12 李四 2 34 23 王武 3 34 4a.id同parent_id 存在关…

MySQL冷备份的跨操作系统还原
数据来源:linux平台mysql版本为5.7 数据去向:windows平台mysql版本为5.7 操作步骤: 第一步:关闭mysql服务 service mysqld stop 第二步:归档linux平台下mysql的数据目录 tar -czvf data.tar.gz /usr/local/mysql/data …

Java 社区领袖联合发文:别慌,Java 仍然是免费的!
开发四年只会写业务代码,分布式高并发都不会还做程序员? >>> 在去年的 Java One 上,Mark Cavage 当时宣布 Oracle 将逐步开源 Oracle JDK 的专有功能(商业特性)。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为何物,详见:http://zh.wikipedia.org/wiki/Postfix 0.关于Postfix postfix的产生是为了替代传统的sendmail.相较于sendmail,postfix在速度。性能和稳定性上都更胜一筹。如今眼下许多的主流邮件服务事实上都在採用postfix. 当我们须要一个轻量级的…
部分人说 Java 的性能已经达到甚至超过 C++,是真的吗?
好多Java程序员都说由于JIT技术的引入,Java的性能已经和C一样了,而且Java的开发效率极高,可以省下60%的时间。请问事实真的是这样吗?我平常也都在写这两个语言,但是因为开发的软件的复杂度不大,并没有感觉到…

Wiki 开源软件
Wiki 是一个协同著作平台或称开放编辑系统。所谓协同工作, 即它能够让浏览网页的人都能够去修订网页,其简介的 ... Wiki 是怎么做到的. Wiki 使用 了简化的语法,替代复杂的HTML,加上WEB 界面的编辑工具,降低内容维护的…
Android studio安装与调试
1.下载安装android studio 下载好之后安装好2.启动报错提示1)进入刚安装的Android Studio目录下的bin目录。找到idea.properties文件,用文本编辑器打开。2)在idea.properties文件末尾添加一行: disable.android.first.runtrue &am…

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

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

strust2自定义interceptor的基本方法及操作
需求:制作一个网站需要用户登陆后才能查看,即一个权限的问题 1.首先明确在用户没登陆前有两个Action请求是可以通过的,即注册和登陆。 2.创建拦截器,如UserLoginInterceptor.java,如下 public class UserLoginIntercep…
使用xdebug分析thinkphp框架函数调用图
开发中需要性能调优,使用xdebug分析thinkphp框架函数调用图。关于xdebug的安装参考这2篇 NetBeans配置Xdebug 远程调试PHP php扩展xdebug安装以及用kcachegrind系统分析1.安装xdebug 需要先去http://www.xdebug.org看看一些文档,xdebug作为php扩展安装 #…

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

java中的类修饰符、成员变量修饰符、方法修饰符。
类修饰符: public(访问控制符),将一个类声明为公共类,他可以被任何对象访问,一个程序的主类必须是公共类。 abstract,将一个类声明为抽象类,没有实现的方法,需要子类提供…
Linux 系统挂载数据盘
Linux 系统挂载数据盘: 适用系统:Linux(Redhat , CentOS,Debian,Ubuntu)* Linux的云服务器数据盘未做分区和格式化,可以根据以下步骤进行分区以及格式化操作。下面的操作将会把数据盘划分为一个…

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

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

创建Maven版Java工程
步骤: 创建成功后,如图: 转载于: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命令复制即可。例如:/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,可以正常跑,然后…

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

[学习笔记]矩阵乘法及其优化dp
1.定义: $c[i][j]\sum a[i][k]\times b[k][j]$ 所以矩阵乘法有条件,(n*m)*(m*p)n*p 即第一个矩阵的列数等于第二个矩阵的行数,否则没有意义。 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创建指定用户特定指定目录权限
指定用户特定指定目录权限需要注意要指定好文件夹的权限,不然会导致nginx不能访问,最好是在root下建立目录,然后 # useradd -d /usr/www -m tempuser# passwd tempuser 回车输入密码 注意一定要带用户名,不然就是修改root!!!# c…

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

c语言初学 循环 的灵活使用小案例
上为流程图 上为代码实现,没有做优化。接下来是效果图。 时间2018.10.01 地点:广东轻工业职业技术学院复制代码 转载于:https://juejin.im/post/5bb1d98a5188255c9a77441a
常见maven引用
json-lib Could not find artifact net.sf.json-lib:json-lib:jar json-lib是需要区分jdk版本的,pom.xml中的配置应加上<classifier>标签,如用jdk15: <dependency><groupId>net.sf.json-lib</groupId><artifactId…