初探ThreadLocal类
2015-04-01 15:33
155 查看
1、ThreadLocal并不是一个Thread,而是Thread的局部变量,当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
2、ThreadLocal类中的方法:(JDK5版本之后支持泛型):
一、void set(T value)
将此线程局部变量的当前线程副本中的值设置为指定值
二、void remove()
移除此线程局部变量当前线程的值
三、protected T initialValue()
返回此线程局部变量的当前线程的“初始值”
四、T get()
返回此线程局部变量的当前线程副本中的值
3、ThreadLocal的原理:
ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单:在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本。
4、JDK API 写道:
该类提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。ThreadLocal 实例通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。
5、使用ThreadLocal的具体例子:
结果如下:
观察输出的结果,我们发现每个线程所产生的序号虽然都共享同一个LocalThreadTest实例,但它们并没有发生相互干扰的情况,而是各自产生独立的序列号,这是因为我们通过ThreadLocal为每一个线程提供了单独的副本。
6、ThreadLocal和同步机制的比较:
相同点:ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题
区别:在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序
设计和编写难度相对较大。
ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal.
概括来说:对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互
不影响。
总结:ThreadLocal是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性。
ThreadLocal模式是为了解决单线程内的跨类跨方法调用的。ThreadLocal不是用来解决对象共享访问问题的,而主要是提供了保持对象的方法和避免参数传递的方便的对象访问方式。一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中访问的是不同的对象。
参考文献:
http://blog.csdn.net/yaerfeng/article/details/7748147
http://blog.csdn.net/lufeng20/article/details/24314381
2、ThreadLocal类中的方法:(JDK5版本之后支持泛型):
一、void set(T value)
将此线程局部变量的当前线程副本中的值设置为指定值
二、void remove()
移除此线程局部变量当前线程的值
三、protected T initialValue()
返回此线程局部变量的当前线程的“初始值”
四、T get()
返回此线程局部变量的当前线程副本中的值
3、ThreadLocal的原理:
ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单:在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本。
4、JDK API 写道:
该类提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。ThreadLocal 实例通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。
5、使用ThreadLocal的具体例子:
package cn.vobile.utils; public class LocalThreadTest { //通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值 private static ThreadLocal<Integer> seNum = new ThreadLocal<Integer>() { protected Integer initialValue() { return 0; } }; public Integer getNextNum() { seNum.set(seNum.get() + 1); return seNum.get(); } public static void main(String[] args) { LocalThreadTest lt = new LocalThreadTest(); // 3个线程共享sn,各自产生序列号 TestClient t1 = new TestClient(lt); TestClient t2 = new TestClient(lt); TestClient t3 = new TestClient(lt); t1.start(); t2.start(); t3.start(); } private static class TestClient extends Thread{ private LocalThreadTest lt; public TestClient(LocalThreadTest lt) { this.lt = lt; } public void run() { // 每个线程打印3个序列号 for (int i = 0; i < 3; i++) { System.out.println("thread[" + Thread.currentThread().getName() + "],lt[" + lt.getNextNum() + "]"); } } } }
结果如下:
thread[Thread-0],lt[1] thread[Thread-0],lt[2] thread[Thread-0],lt[3] thread[Thread-1],lt[1] thread[Thread-1],lt[2] thread[Thread-1],lt[3] thread[Thread-2],lt[1] thread[Thread-2],lt[2] thread[Thread-2],lt[3]
观察输出的结果,我们发现每个线程所产生的序号虽然都共享同一个LocalThreadTest实例,但它们并没有发生相互干扰的情况,而是各自产生独立的序列号,这是因为我们通过ThreadLocal为每一个线程提供了单独的副本。
6、ThreadLocal和同步机制的比较:
相同点:ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题
区别:在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序
设计和编写难度相对较大。
ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal.
概括来说:对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互
不影响。
总结:ThreadLocal是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性。
ThreadLocal模式是为了解决单线程内的跨类跨方法调用的。ThreadLocal不是用来解决对象共享访问问题的,而主要是提供了保持对象的方法和避免参数传递的方便的对象访问方式。一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中访问的是不同的对象。
参考文献:
http://blog.csdn.net/yaerfeng/article/details/7748147
http://blog.csdn.net/lufeng20/article/details/24314381
相关文章推荐
- Oracle 数据库针对表主键列并发导致行级锁简单演示
- MySQL中SELECT+UPDATE处理并发更新问题解决方案分享
- Go语言并发模型的2种编程方案
- Go语言并发技术详解
- JAVA多线程与并发学习总结分析
- JAVA多线程和并发基础面试问答(翻译)
- 线程池的理解
- 自旋锁学习系列(3):指数后退技术
- JAVA并发编程
- java实现简单的并行计算框架
- Java之线程安全的简单理解
- 使用Python进行并发编程
- 初识英特尔线程构建模块之内存管理tbb_malloc
- 并发和并行的区别
- PV与并发之间换算的算法换算公式
- Struts2中TreadLocal设计模式详解
- 利于ThreadLocal管理Hibernate Session
- shell 并发
- 聊聊并发-Java中的阻塞队列
- 项目问题总结一、全局变量引起的并发问题