科技报道|一次性搞清楚,Java并发编程在各主流框架中的应用,保证看懂( 三 )
ThreadLocal 的应用及源码解析ThreadLocal 又称为线程本地存储区(Thread Local Storage , 简称为 TLS) , 每个线程都有自己的私有的本地存储区域 , 不同线程之间彼此不能访问对方的 TLS 区域 。 使用 ThreadLocal 变量 的 set(T value) 方法 可以将数据存入该线程本地存储区 , 使用 get() 方法 可以获取到之前存入的值 。
ThreadLocal 的常见应用
不使用 ThreadLocal 。
public class SessionBean {public static class Session {private String id;public String getId() {return id;}public void setId(String id) {this.id = id;}}public Session createSession() {return new Session();}public void setId(Session session, String id) {session.setId(id);}public String getId(Session session) {return session.getId();}public static void main(String[] args) {//没有使用ThreadLocal , 在方法间共享session需要进行session在方法间的传递new Thread(() -> {SessionBean bean = new SessionBean();Session session = bean.createSession();bean.setId(session, "susan");System.out.println(bean.getId(session));}).start();}}上述代码中 , session 需要在方法间传递才可以修改和读取 , 保证线程中各方法操作的是一个 。 下面看一下使用 ThreadLocal 的代码 。
public class SessionBean {//定义一个静态ThreadLocal变量session , 就能够保证各个线程有自己的一份 , 并且方法可以方便获取 , 不用传递private static ThreadLocal session = new ThreadLocal<>();public static class Session {private String id;public String getId() {return id;}public void setId(String id) {this.id = id;}}public void createSession() {session.set(new Session());}public void setId(String id) {session.get().setId(id);}public String getId() {return session.get().getId();}public static void main(String[] args) {new Thread(() -> {SessionBean bean = new SessionBean();bean.createSession();bean.setId("susan");System.out.println(bean.getId());}).start();}}在方法的内部实现中 , 直接可以通过 session.get() 获取到当前线程的 session , 省掉了参数在方法间传递的环节 。
ThreadLocal 的实现原理
一般 , 类属性中的数据是多个线程共享的 , 但 ThreadLocal 类型的数据 声明为类属性 , 却可以为每一个使用它(通过 set(T value)方法)的线程存储线程私有的数据 , 通过其源码我们可以发现其中的原理 。
public class ThreadLocal {/*** 下面的 getMap()方法 传入当前线程 , 获得一个ThreadLocalMap对象 , 说明每一个线程维护了* 自己的一个 map , 保证读取出来的value是自己线程的 。** ThreadLocalMap 是ThreadLocal静态内部类 , 存储value的键值就是ThreadLocal本身 。** 因此可以断定 , 每个线程维护一个ThreadLocalMap的键值对映射Map 。 不同线程的Map的 key值 是一样的 ,* 都是ThreadLocal , 但 value 是不同的 。*/public T get() {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) {ThreadLocalMap.Entry e = map.getEntry(this);if (e != null) {@SuppressWarnings("unchecked")T result = (T)e.value;return result;}}return setInitialValue();}public void set(T value) {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);}}ThreadLocal 在 Spring 中的使用
Spring 事务处理的设计与实现中大量使用了 ThreadLocal 类 , 比如 , TransactionSynchronizationManager 维护了一系列的 ThreadLocal 变量 , 用于存储线程私有的 事务属性及资源 。 源码如下 。
推荐阅读
- 所持股份|万兴科技:公司控股股东、实际控制人吴太兵质押150万股
- 发布公告|数量过半!博创科技:天通股份累计减持约150万股
- 英雄科技聊数码|蔡崇信有实力买下篮网,那身价3200亿的马云,能买下几支NBA球队
- 光明网|多几个角度看待“集中清退研究生”
- 前沿军事报道|普京4个字回应十分解气,中俄率先突破!美国要求疫苗必须无偿供应
- 科技前沿阵地|涨疯了!海思安防芯片遭哄抬“围剿”
- 月影浓|吴亦凡机械造型走秀 垫肩披风搭银框眼镜科技感足
- 中国历史发展过程|中国历史发展过程.中国的科技史界过去半个多世纪
- 天津|桂发祥:不再持有昆汀科技股份
- 消费|减持!天通股份:减持博创科技约32万股
