ThreadLocal的意义和实现
可以想像,如果一个对象的可变的变量被多个线程访问时,必然是不安全的。
在单线程应用可能会维持一个全局的数据库连接,并在程序启动时初始化这个连接对象,从而避免在调用每个方法时都传递一个Connection对象。ThreadUnsafe类就是这样做的:
public class ThreadUnsafe {private static Connection connection = DriverManager.getConnection(DB_URL);public void Connection getConnection{ /* 在多线程应用中,connection 在被多个线程访问 */return connection;} }
但是JDBC连接对象不一定是线程安全的,在多个线程访问到Connection时,就可能出现安全问题。为了解决这个问题,ThreadLocal类提供了安全的做法。
通过将JDBC的Connection对象封装在ThreadLocal对象中,当每个线程访问需要Connection对象时,ThreadLocal对象返回的是一个副本。
public class ThreadUnsafe {private static ThreadLocal<Connection> connectionHodler = new ThreadLocal<>{public Connection initialValue() {return DriverManager.getConnection(DB_URL);}} public void Connection getConnection{ /* 即使多个线程可以访问,依然安全 */return connectionHolder.get();} }
ThreadLocal是如何实现这种功能?
首先,在Thread类中有一个threadLocals的实例变量,这是一个Map,保存了与线程相关的ThreadLocal对象封装的变量。
/* ThreadLocal values pertaining to this thread. This map is maintained* by the ThreadLocal class. */ThreadLocal.ThreadLocalMap threadLocals = null;
当线程初次调用ThreadLocal对象的get方法时,就会调用initialValue()来获取初始值。
/*** 返回ThreadLocal封装的对象。*/public T get() {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) { /* 首次调用map为null */ThreadLocalMap.Entry e = map.getEntry(this);if (e != null) {@SuppressWarnings("unchecked")T result = (T)e.value;return result;}}return setInitialValue(); /* 首次调用的返回值 */}/*** 初始化封装在ThreadLocal中对象的值。*/private T setInitialValue() {T value = initialValue();Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value); //为什么键值是ThreadLocal对象?,因为一个线程对象可能有使用多个ThreadLocal封闭的变量elsecreateMap(t, value);return value;}/*** 更新封装在ThreadLocal中对象的值*/public void set(T value) {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);} public void remove() {ThreadLocalMap m = getMap(Thread.currentThread());if (m != null)m.remove(this);}ThreadLocalMap getMap(Thread t) {return t.threadLocals;}/*** 创建一个Map,用于保存ThreadLocal和其封装的对象。*/void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue);}
注意:ThreadLocalMap在ThreadLocal类中声明,却是在Thread类中使用的,原因在于,当线程结束时,这些特定于线程的值保存在Thread对象中,当线程终止后,这些值会作为垃圾回收。
ThreadLocal类实现的是一种线程封闭技术。将变量封闭在单线程中,从而避免同步。
参考: 《Java Concurrency in Practice》 P35&P37
转载于:https://www.cnblogs.com/yvkm/p/10664109.html
ThreadLocal的意义和实现相关推荐
- 用了三年 ThreadLocal 今天才弄明白其中的道理
来自:码匠笔记 ThreadLocal 对于大家并不陌生,每个人应该多少都用过,或者接触过,那么你真的了解她吗?我也是今天才揭开了她的神秘面纱. 看完这篇文章你将 GET 如下知识点: 什么是 Thr ...
- Multipart自定义资源限制文件大小限制设计——aop切面怎么才能切入Multipart的文件大小拦截?
Multipart自定义资源限制文件大小限制设计--aop切面怎么才能切入Multipart的文件大小拦截? author:陈镇坤27 创建时间:2022年1月23日 创作不易,转载请注明来源 摘要: ...
- ThreadLocal为什么要使用弱引用和内存泄露问题
在threadlocal的生命周期中,都存在这些引用. 看下图: 实线代表强引用,虚线代表弱引用. 下面来看两个问题: 1为什么要使用弱引用 2为什么会出现内存泄露问题 - 为什么要使用弱引用 - 每 ...
- 面试:说说你对 ThreadLocal 的认识?
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! ThreadLocal的原理和实现 ThreadLoal ...
- 并发基础(十) 线程局部副本ThreadLocal之正解
什么是ThreadLocal ThreadLocal是线程局部变量,所谓的线程局部变量,就是仅仅只能被本线程访问,不能在线程之间进行共享访问的变量.在各个Java web的各种框架中ThreadLoc ...
- Java8 ThreadLocal 源码分析
可参考文章: Java8 IdentityhashMap 源码分析 IdentityhashMap 与 ThreadLocalMap 一样都是采用线性探测法解决哈希冲突,有兴趣的可以先了解下 Iden ...
- j2ee servlet 和 threadlocal ,synchronized 与 web容器
在传统的Web开发中,我们处理Http请求最常用的方式是通过实现Servlet对象来进行Http请求的响应.Servlet是J2EE的重要标准之一,规定了Java如何响应Http请求的规范.通过Htt ...
- ThreadLocal以及增强
多线程的本质就是增加任务的并发,提高效率.但是又要控制任务不错乱,可以通过锁来控制资源的访问. 除了控制资源的访问外,我们可以通过增加资源来保证所有对象的线程安全.比如100个人填写个人信息表,如果只 ...
- 多线程与高并发(五):强软弱虚四种引用以及ThreadLocal的原理与源码
上节回顾 AQS(CLH的变种) 因为新加进来的节点要查看前面的节点的状态,所以使用的是双向链表. AQS的底层是 CAS + Volitile,用CAS替代了锁整个链表的操作. 公平锁:上来先排队 ...
最新文章
- linux 快速删除大量/大文件
- Android悬浮按钮锚点位置,Android 滑动定位+吸附悬停效果实现
- 前端wxml取后台js变量值_这些鲜为人知的前端冷知识,你都GET了吗?
- 深度学习:什么是自编码器(Autoencoder)
- 小结SpringMVC(二)
- AutoCAD2007专业版
- 体脂的计算Java_简单测试体脂率的两种经验公式
- CodeForces 595A Vitaly and Night
- 计算机中单位换算tb,bit Byte KB MB GB TB 单位换算
- 用计算机玩吃鸡,W10电脑系统玩吃鸡游戏会卡顿怎么办
- 后端开发面试自我介绍_java工程师面试自我介绍范文
- 软件测试工作中有哪些常用的工具?
- Acdream 1729 Crime
- 介绍一款web端的截图工具
- php随机缩略图,实现随机缩略图的简单思路和phpcms随机缩略图两种方法
- 没有链克口袋,但我一样玩游戏掘金
- JavaScript 04 — Array Cardio Day 1
- Apple Pay入华一年:称雄美国在华败北
- Macbooster8最新版Mac清理工具
- KDB_Database_Link 使用介绍