Java并发机制(4)--ThreadLocal线程本地变量(转)
个人理解:
说明:看了博客园中大神写的ThreadLocal的详解,感觉还是有些迷糊,下面用自己的理解简单描述下ThreadLocal的机制(难免有误);
1、首先ThreadLocal用于存储对应线程的本地变量,放在哪里呢?每一个线程维护一个threadlocals(这个threadlocals我认为是由ThreadLcoal创建的,是当前线程上的属性,多个ThreadLocal只创建一个:通过ThreadLocal中的createMap方法: t.threadLocals = new ThreadLocalMap(this, firstValue); ),它事实上就是一个ThreadLocalMap,是ThreadLocal的内部类,可以理解为一张Map表,其中包含了Entry键值对,故线程的本地变量就放在这个Entry中:Entry:<ThreadLocal,value>形式,键值对里的ThreadLocal我认为是你用的时候new出来的ThreadLocal,而不是每个线程所维护的那一个ThreadLoca。(不是很确定,但是想到一个线程要放多个变量的话,每个变量new一个ThreadLocal,这些ThreadLocal做为key放在线程所维护的那个ThreadLocalMap中?)。
2、由1中知道,一个ThreadLocal只能存放一个线程的本地变量,所以要存放第二个线程的本地变量,就应该在new ThreadLocal进行存储,所以 private static final ThreadLocal <T> t1=new Threadlocal<>() 这句话可以写在工具类中,且作为静态成员变量使用。
这里我一开始理解错误:把ThreadLocalMap理解成类似于HashMaple了,然后ThreadLocal保存了所有线程的本地变量,这样一个ThreadLocal就可以了?那么多线程访问一个ThreadLocal(共享)依然需要加锁,失去了原来的意义。
3、ThreadLocal的方法理解(源码分析):
3.1、threadlocal.get()方法:
step1:根据当前线程t获取对应的TheradLocalMap;
step2:如果ThreadLocalMap!=null;获取内部的Entry,返回val,结束;
如果ThreadLocalMap==null,调用setInitialValue()方法设置初始值;
step3:setInitialValue()方法判断是否有ThreadLocalMap,(没有则创建),
并调用initialValue()方法获得初始value,这个value=null;
所以,new 出来的Threadlocal要先set(value),然后get(),否则get到null;
或者也可以重写initialValue方法(默认返回一个初始值);
3.2、threadlocal.set()方法:赋值,不多描述。
4、弱引用问题:ThreadLocalMap使用ThreadLocal的弱引用作为key,,如果一个ThreadLocal没有外部强引用引用他,那么系统gc的时候,这个ThreadLocal势必会被回收,这样一来,ThreadLocalMap中就会出现key为null的Entry,无法访问到这些value,如果当前线程再迟迟不结束的话,这些key为null的Entry的value就会一直存在一条强引用链:Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value,永远无法回收,造成内存泄露。
JDK建议将ThreadLocal变量定义成private static的,这样的话ThreadLocal的生命周期就更长,并主动调用remove函数释放。
总结如下:
首先,要区分threadlocals、ThreadLocalMap、ThreadLocal这三者。
其次,ThreadLcoal的主要机制如下。
(1)每个线程Thread内部有一个threadlocals属性,它是ThreadLocal.ThreadLocalMap类型的,内部的Entry<ThreadLocal,value>用来保存变量的副本,只供线程自己使用。
(2)最开始,threadlocals是空的,通过Threadlocal的get或者set方法可以初始化threadlocals(调用createMap方法,源代码在1种),然后你每存一个变量副本,需要new ThreadLocal()出来,存几个new几个,threadlocals以该ThreadLocal为key,变量副本为value进行保存。
(2)我们可以通过ThreadLocal.get()获取对应的ThreadLocal的value。通过ThreadLcoal.set(value)来设置更改threadlocals中的值。
参考资料:
1、博客园-海子-http://www.cnblogs.com/dolphin0520/p/3920407.html
2、http://www.iteye.com/topic/103804
3、http://www.cnblogs.com/xzwblog/p/7227509.html
以下给出两段实例代码,也来自上述参考资料:
1、hibernate中典型的ThreadLocal的应用,获取session;
...
private static final ThreadLocal threadSession = new ThreadLocal(); //类成员 public static Session getSession() throws InfrastructureException {
Session s = (Session) threadSession.get();
try {
if (s == null) {
s = getSessionFactory().openSession();
threadSession.set(s);
}
} catch (HibernateException ex) {
throw new InfrastructureException(ex);
}
return s;
}
2、
public class Test {
ThreadLocal<Long> longLocal = new ThreadLocal<Long>();
ThreadLocal<String> stringLocal = new ThreadLocal<String>();
public void set() {
longLocal.set(Thread.currentThread().getId());
//这里先获取每一个线程thread的ThreadLocalMap,然后map.set(this, value),this就是当前的ThreadLocal,value就是getId的值,也就为每个线程创建完副本,并存放入线程的ThreadLocalMap中,从而实现了线程本地变量的副本创建。
stringLocal.set(Thread.currentThread().getName());
} public long getLong() {
return longLocal.get();
} public String getString() {
return stringLocal.get();
} public static void main(String[] args) throws InterruptedException {
final Test test = new Test(); test.set();
System.out.println(test.getLong());
System.out.println(test.getString()); Thread thread1 = new Thread(){
public void run() {
test.set();
System.out.println(test.getLong());
System.out.println(test.getString());
};
};
thread1.start();
thread1.join(); System.out.println(test.getLong());
System.out.println(test.getString());
}
}

------------------------------------------------------------------------------------------终-----------------------------------------------------------------------------------------------------------------------------------------------
详情移步:博客园-海子-http://www.cnblogs.com/dolphin0520/p/3920407.html
Java并发机制(4)--ThreadLocal线程本地变量(转)的更多相关文章
- Threadlocal线程本地变量理解
转载:https://www.cnblogs.com/chengxiao/p/6152824.html 总结: 作用:ThreadLocal 线程本地变量,可用于分布式项目的日志追踪 用法:在切面中生 ...
- ThreadLocal 线程本地变量 及 源码分析
■ ThreadLocal 定义 ThreadLocal通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题 当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量 ...
- ThreadLocal线程本地变量
首先说明ThreadLocal存放的值是线程内共享的,线程间互斥的,主要用于线程内共享一些数据,避免通过参数来传递,这样处理后,能够优雅的解决一些实际问题,比如hibernate中的OpenSessi ...
- 深入理解线程本地变量ThreadLocal
ThreadLocal理解: 假设在多线程并发环境中.一个可变对象涉及到共享与竞争,那么该可变对象就一定会涉及到线程间同步操作,这是多线程并发问题. 否则该可变对象将作为线程私有对象,可通过Threa ...
- Java并发(二十):线程本地变量ThreadLocal
ThreadLocal是一个本地线程副本变量工具类. 主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰,在高并发场景下,可以实现无状态的调用,特别适用于各个线程依赖不同的 ...
- 深入理解java:2.4. 线程本地变量 java.lang.ThreadLocal类
ThreadLocal,很多人都叫它做线程本地变量,也有些地方叫做线程本地存储,其实意思差不多. 可能很多朋友都知道ThreadLocal为变量在每个线程中都创建了一个副本,那样每个线程可以访问自己内 ...
- 线程本地变量ThreadLocal
一.本地线程变量使用场景 并发应用的一个关键地方就是共享数据.如果你创建一个类对象,实现Runnable接口,然后多个Thread对象使用同样的Runnable对象,全部的线程都共享同样的属性.这意味 ...
- java线程本地变量
ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是threadlocalvariable(线程局部变量).也许把它命名为Thre ...
- 线程本地变量ThreadLocal源码解读
一.ThreadLocal基础知识 原始线程现状: 按照传统经验,如果某个对象是非线程安全的,在多线程环境下,对对象的访问必须采用synchronized进行线程同步.但是Spring中的各种模板 ...
随机推荐
- ajax读本地文件
前置条件: 1. 编辑器,我用的是HbuilderX,解压即食,非常美味,点击传送门. 2. jQuery.min.js,点击传送门. 简单的项目目录: a. test.html内容 <!DOC ...
- [源码解析] NVIDIA HugeCTR,GPU 版本参数服务器---(7) ---Distributed Hash之前向传播
[源码解析] NVIDIA HugeCTR,GPU 版本参数服务器---(7) ---Distributed Hash之前向传播 目录 [源码解析] NVIDIA HugeCTR,GPU 版本参数服务 ...
- wmware15安装centos7.9
详细步骤如下: 下面位置应该写:D:\k8s\k8s-master01 也可以桥接 下面可以删除 从官方下载的,不需要test,所以选择第一个 默认英文的即可 改为上海 保持默认 配置静态ip 主机名 ...
- 你的程序员女孩「GitHub 热点速览 v.22.09」
本周最火的项目要数上周推荐的开源项目 How to Cook,火到一周涨了 18k+ star,但网友对它的定量烹饪方法褒贬不一.在本人看来,烹饪本就是一门"玄学",萝卜青菜各有所 ...
- 微服务从代码到k8s部署应有尽有系列(九、事务精讲)
我们用一个系列来讲解从需求到上线.从代码到k8s部署.从日志到监控等各个方面的微服务完整实践. 整个项目使用了go-zero开发的微服务,基本包含了go-zero以及相关go-zero作者开发的一些中 ...
- Hadoop配置文件汇总
(一)基本集群配置 共8个配置文件 hadoop-env.sh yarn-env.sh mapred-env.sh core-site.xml hdfs-site.xml yarn-site.xml ...
- 哈工大 信息安全 实验 Snort与单台防火墙联动实验
XX大学XX学院 <网络攻击与防御> 实验报告 实验报告撰写要求 实验操作是教学过程中理论联系实际的重要环节,而实验报告的撰写又是知识系统化的吸收和升华过程,因此,实验报告应该体现完整性. ...
- AntBlazor Theme in ABP Framework
介绍 ABP抽象了主题系统,将已有的UI更改到其他的UI框架非常简单,本文介绍了如何将主题切换为AntBlazor Theme. 源码以及示例在Gihub开源. Lsw.Abp.AntDesignUI ...
- JZ-066-机器人的运动范围
机器人的运动范围 题目描述 地上有一个m行和n列的方格.一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子. 例如,当k ...
- MAC VMware配置Kali linux
一.部署kali虚拟机 1.选择vmaware fusion12,放弃parallels,因为我用的是MAC系统,所以提供的是VMware的mac版本 2.VMware fusion12邀请码: ZF ...