ThreadLocal与局部变量
来源:互联网 发布:美工设计学习 编辑:程序博客网 时间:2024/06/05 19:58
ThreadLocal和线程局部变量有什么区别,我们先看一段代码,如下:
public class ThreadLocalLearn { static ThreadLocal<IntHolder> tl = new ThreadLocal<IntHolder>(){ protected IntHolder initialValue() { return new IntHolder(); } }; public static void main(String args[]) { for(int i=0; i<5; i++) { Thread th = new Thread(new ThreadTest(tl, i)); th.start(); } }}class ThreadTest implements Runnable{ ThreadLocal<IntHolder> tl ; //threadlocal变量 int i; int a = 3; //线程局部变量 public ThreadTest(ThreadLocal<IntHolder> tl, int i) { super(); this.tl = tl; this.i = i; } @Override public void run() { tl.get().increAndGet(); a++; System.out.println(tl.get().getA() + " "); System.out.println("a : " + a); }}class IntHolder{ int a = 1; public int getA() { return a; } public void setA(int a) { this.a = a; } public int increAndGet() { return ++a; }}
代码的运行结果如下:
2 a : 42 a : 42 a : 42 a : 42 a : 4
可以看到,局部变量和ThreadLocal起到的作用是一样的,保证了并发环境下数据的安全性。那就是说,完全可以用局部变量来代替ThreadLocal咯,这样想法对么?我们看一看官方对于ThreadLocal的描述:
This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its {@code get} or {@code set} method) has its own, independently initialized copy of the variable. {@code ThreadLocal} instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).
翻译起来就是
ThreadLocal提供的是一种线程局部变量。这些变量不同于其它变量的点在于每个线程在获取变量的时候,都拥有它自己相对独立的变量初始化拷贝。ThreadL:ocal的实例一般是私有静态的,可以做到与一个线程绑定某一种状态。PS:有更好的翻译请指教。
所以就这段话而言,我们知道ThreadLocal不是为了满足多线程安全而开发出来的,因为局部变量已经足够安全。ThreadLocal是为了方便线程处理自己的某种状态。
可以看到ThreadLocal实例化所处的位置,是一个线程共有区域。好比一个银行和个人,我们可以把钱存在银行,也可以把钱存在家。存在家里的钱是局部变量,仅供个人使用;存在银行里的钱也不是说可以让别人随便使用,只有我们以个人身份去获取才能得到。所以说ThreadLocal封装的变量我们是在外面某个区域保存了处于我们个人的一个状态,只允许我们自己去访问和修改的状态。
ThreadLocal同时提供了初始化的机制,在实例化时重写initialValue()方法,便可实现变量的初始化工作
//method 1 static ThreadLocal<IntHolder> tl = new ThreadLocal<IntHolder>(){ protected IntHolder initialValue() { return new IntHolder(); } }; //method 2 IntHolder intHolder = new IntHolder(); static ThreadLocal<IntHolder> tl = new ThreadLocal<IntHolder>(){ protected IntHolder initialValue() { return intHolder; } };
方法一和方法二都可以实现初始化工作,但是方法二不能保证线程变量的安全性,因为引用拷贝指向的是同一个实例,对引用拷贝的修改,等同于对实例的修改。
当然,也可以在判断ThreadlLocal获取数据为空时,在线程内部为ThreadLocal实例化一个数据。如下:
if(null == tl.get()) { tl.set(new IntHolder());}
为什么我们需要ThreadLocal来实现在自身内部外创建一个有关自己的状态呢?其实可以完全使用参数传递内部参数,就像我在自己随便放钱一样!这里要注意的是,我们定义一个方法的时候,并不是参数越多越好,有些共有参数,我们应该尽量设为全局,便于系统的可维护性与可扩展性。另一个角度考虑,银行也有其存在的价值,ThreadLocal会简化我们的编程,毕竟它是安全的。
根据ThreadLocal原理,我们自己实现一个:
import java.util.concurrent.ConcurrentHashMap;public class ThreadLocalVar<T> { public T initVaribale() { return null; } volatile ConcurrentHashMap<Thread, T> map = new ConcurrentHashMap<Thread, T>(); public void put(T t) { map.put(Thread.currentThread(), t); } public T get() { T value = map.get(Thread.currentThread()); if(null == value) { T t = initVaribale(); if(null == t) { return null; } map.put(Thread.currentThread(), t); return t; } else { return value; } }}
有兴趣也可以去阅读jdk中ThreadLocal的源码~
- ThreadLocal与局部变量
- 线程局部变量ThreadLocal
- ThreadLocal 线程局部变量
- 线程局部变量ThreadLocal
- ThreadLocal线程局部变量
- 线程局部变量ThreadLocal
- 线程局部变量ThreadLocal
- ThreadLocal 线程局部变量
- ThreadLocal 线程局部变量
- 理解ThreadLocal(线程局部变量)
- 线程-ThreadLocal-线程局部变量
- 理解ThreadLocal(线程局部变量)
- ThreadLocal(线程局部变量)
- 线程局部变量ThreadLocal的认识
- java实现线程局部变量:ThreadLocal
- JAVA的Thread局部变量ThreadLocal
- 03____线程局部变量(ThreadLocal)
- JAVA的Thread局部变量ThreadLocal
- Android studio怎么上传代码到Conding
- Select组件
- 量化交易 Alpha Algo 1. 简单的双均线策略
- 《重构-改善既有代码的设计》-第1例:租赁影片(2)
- MySQL数据表相关操作-完整性约束条件
- ThreadLocal与局部变量
- 马士兵java学习之路
- 分享:初涉Pysqlite遇到的问题
- 斐波那契数列
- TurtleBot基于已知地图的自主导航
- synchronized 和 beginTransaction 死锁的一个例子
- C#中SqlDataAdapter的使用小结
- windows批处理学习2--小例子
- this is my first Blog