关于ThreadLocal的一点理解
来源:互联网 发布:b2b软件有哪些 编辑:程序博客网 时间:2024/05/21 06:59
这个问题困扰了自己挺久,知道在知乎上看到一个大神的回答,顿时有种拨开云雾见青天的感觉。
https://www.zhihu.com/question/23089780
在前人的基础上再次稍加总结,以加深印象。
ThreadLocal并不是为了解决并发访问数据过程中可能存在的数据不一致问题,事实上ThreadLocal是为了解决变量在线程内部各个方法之间共享的问题。
class TestGoWan implements Runnable{ private int id; public TestGoWan(int id) { super(); this.id = id; } private static ThreadLocal<GongJiaoCard> tl = new ThreadLocal<GongJiaoCard>(); public void run() { GongJiaoCard g = new GongJiaoCard((int)(Math.random()*100)); tl.set(g); this.goByBus(); this.goByMetro(); } public void goByBus(){ System.out.println("线程id"+id+"拿着公交卡id:"+tl.get().getId()+"坐公交!"); } public void goByMetro(){ System.out.println("线程id"+id+"拿着公交卡id:"+tl.get().getId()+"坐地铁!"); }}class GongJiaoCard{ private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } public GongJiaoCard(int id) { super(); this.id = id; }}public class TestThread{ public static void main(String[] args) { for(int i = 1; i<6; i++){ Thread t = new Thread(new TestGoWan(i)); t.start(); } }}
代码运行结果如下:
线程id4拿着公交卡id:56坐公交!线程id2拿着公交卡id:14坐公交!线程id2拿着公交卡id:14坐地铁!线程id3拿着公交卡id:36坐公交!线程id5拿着公交卡id:37坐公交!线程id1拿着公交卡id:48坐公交!线程id5拿着公交卡id:37坐地铁!线程id3拿着公交卡id:36坐地铁!线程id4拿着公交卡id:56坐地铁!线程id1拿着公交卡id:48坐地铁!
可以看到每个线程拿的都是自己的公交卡,也就是说ThreadLocal中保存的变量在同一线程的不同方法(goByBus、goByMetro)之间可以共享,但是在不同的线程之间是隔离的。
要想实现变量在同一线程的不同方法之间共享,而在线程之间隔离貌似用如下方式也可以
class TestGoHaveFun implements Runnable{ private int id; private GongJiaoCard g; public TestGoHaveFun(int id) { super(); this.id = id; } public void run() { g = new GongJiaoCard((int)(Math.random()*100)); goByBus(); goByMetro(); } public void goByBus(){ System.out.println("线程id"+id+"拿着公交卡id:"+g.getId()+"坐公交!"); } public void goByMetro(){ System.out.println("线程id"+id+"拿着公交卡id:"+g.getId()+"坐地铁!"); } }
这个问题暂且放下,待哪天真正弄明白再来补充。
接下来分析从ThreadLocal源码的角度分析下其实现原理。
先从ThreadLocal核心的set和get方法开始:
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }
它先拿到当前线程,并获得当前线程的的ThreadLocalMap的变量,这个ThreadLocalMap是ThreadLocal的内部类。拿到这个map后,以当前的 ThreadLocal对象为键,参数value为值将此键值对保存到此map中。这样,由于这个ThreadLocalMap是通过当前线程获取的,那么保存在该map中的键值对就是当前线程相关的。
阅读全文
0 0
- 关于ThreadLocal的一点理解
- 关于ThreadLocal的一点理解
- ThreadLocal的一点理解
- ThreadLocal的一点个人理解
- 对ThreadLocal的一点理解
- 关于ThreadLocal的理解
- 关于ThreadLocal的理解
- 关于ThreadLocal的理解
- 关于ThreadLocal的理解
- 关于threadlocal的理解
- 关于ThreadLocal的初步理解
- 关于ThreadLocal类的理解
- 关于ThreadLocal引起内存泄漏的理解
- 关于StrutsFormBean 的一点理解
- 关于Action的一点理解
- 关于闪光灯的一点理解
- 关于fourcc的一点理解
- 关于typedef的一点理解
- [Oracle 11g r2(11.2.0.4.0)]RAC集群启动介绍
- Hibernate框架-cascade属性
- 【未完待续】greenplum AO
- synchronized与Lock 擂台之战
- 浏览器兼容性1—颜色(color属性)
- 关于ThreadLocal的一点理解
- MiKiShow
- vs使用mfc类向导重写父类
- SpringMVC的搭建
- JAVASE入门---我对强转与多态的理解
- [C# 网络编程系列]专题五:TCP编程
- [Lintcode] #70 二叉树的层次遍历 II
- 嵌入式 uboot命令及内核启动参数
- postgres数据库查看用户权限