ThreadLocal是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性。
在Java的多线程编程中,为保证多个线程对共享变量的安全访问,通常会使用synchronized来保证同一时刻只有一个线程对共享变量进行操作。但在有些情况下,synchronized不能保证多线程对共享变量的正确读写。例如类有一个类变量,该类变量会被多个类方法读写,当多线程操作该类的实例对象时,如果线程对类变量有读取、写入操作就会发生类变量读写错误,即便是在类方法前加上synchronized也无效,因为同一个线程在两次调用方法之间时锁是被释放的,这时其它线程可以访问对象的类方法,读取或修改类变量。这种情况下可以将类变量放到ThreadLocal类型的对象中,使变量在每个线程中都有独立拷贝,不会出现一个线程读取变量时而被另一个线程修改的现象。
下面是ThreadLocal的实现原理
public class SimpleThreadLocal {
private Map valueMap = Collections.synchronizedMap(new HashMap());
public void set(Object newValue) {
valueMap.put(Thread.currentThread(), newValue);①键为线程对象,值为本线程的变量副本
}
public Object get() {
Thread currentThread = Thread.currentThread();
Object o = valueMap.get(currentThread);②返回本线程对应的变量
if (o == null && !valueMap.containsKey(currentThread)) {③如果在Map中不存在,放到Map
中保存起来。
o = initialValue();
valueMap.put(currentThread, o);
}
return o;
}
public void remove() {
valueMap.remove(Thread.currentThread());
}
public Object initialValue() {
return null;
}
}
其中 initalValue是protected的,留给子类实现,默认返回null值。
一个demo
package TreaditionThread;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadLocalTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < 2; i++) {
exec.execute(new Task());
}
exec.shutdown();
}
}
class Task implements Runnable {
public void run() {
// TODO Auto-generated method stub
MyThreadLocalData.getInstanceMap().put("key",
Thread.currentThread().getName());
new A().get();
new B().get();
}
}
class A {
public void get() {
HashMap<String, Object> m = MyThreadLocalData.getInstanceMap();
if (m != null) {
System.out.println("A:" + m.get("key"));
}
}
}
class B {
public void get() {
HashMap<String, Object> m = MyThreadLocalData.getInstanceMap();
if (m != null) {
System.out.println("B:" + m.get("key"));
}
}
}
class MyThreadLocalData {
// 每个线程的专属map
private static ThreadLocal<HashMap<String, Object>> data = new ThreadLocal<HashMap<String, Object>>();
public static HashMap<String, Object> getInstanceMap() {
HashMap<String, Object> m = data.get();
if (m == null) {
m = new HashMap<String, Object>();
data.set(m);
}
return data.get();
}
}
output:
A:pool-1-thread-1
A:pool-1-thread-2
B:pool-1-thread-1
B:pool-1-thread-2
分享到:
相关推荐
java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多...
简单分析Java线程编程中ThreadLocal类的使用共4页.pdf.zip
早在 JDK 1.2 的时代,java.lang.ThreadLocal 就诞生了,它是为了解决多线程并发问题而设计的,只不过设计得有些难用,所以至今没有得到广泛使用。其实它还是挺有用的,不相信的话,我们一起来看看这个例子吧。 一个...
资源名称:Java多线程与并发库高级应用视频教程22集资源目录:【】01传统线程技术回顾【】02传统定时器技术回顾【】03传统线程互斥技术【】04传统线程同步通信技术【】04传统线程同步通信技术_分割纪录【】05线程...
入研究java.lang.ThreadLocal类.docx
synchronized关键字不属于方法特征签名的一部分,所以可以在覆盖方法的时候加上去。...如果在一个类内部都是使用synchronized关键字定义了方法f(),g()。那么当使用这个类的实例调用f()时,就不能再调用g()方法。
Java资料—详解ThreadLocal ;Java资料—详解ThreadLocal ;Java资料—详解ThreadLocal ;Java资料—详解ThreadLocal Java资料—详解ThreadLocal
深入研究java.lang.ThreadLocal类。ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是 threadlocalvariable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。
java 简单的ThreadLocal示例
主要介绍了Java多线程编程之ThreadLocal线程范围内的共享变量,本文讲解了ThreadLocal的作用和目的、ThreadLocal的应用场景、ThreadLocal的使用实例等,需要的朋友可以参考下
主要介绍了Java线程编程中ThreadLocal类的使用,包括使用其对共享变量的操作的分析,需要的朋友可以参考下
ThreadLocal保证一个类的实例变量在各个线程中都有一份单独的拷贝, 从而不会影响其他线程中的实例变量
详解java底层实现原理,ThreadLocal底层实现的数据结构,为什么不会导致内存泄露
NULL 博文链接:https://justsee.iteye.com/blog/791919
java多线程安全性基础介绍 线程安全 正确性 什么是线程安全性 原子性 竞态条件 i++ 读i ++ 值写回i 可见性 JMM 由于cpu和内存加载速度的差距,在两者之间增加了多级缓存导致,内存并不能直接对cpu可见。 ...
Java线程:概念与原理 Java线程:创建与启动 Java线程:线程状态的转换 ...Java线程:深入ThreadLocal 一、标准例子 二、不用ThreadLocal 三、自己实现个ThreadLocal 四、透过现象看本质 Java线程:大总结
java 多线程 ThreadLocal
主要介绍了Java单线程ThreadLocal串值问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
关于线程变量ThreadLocal的介绍以及说明. 关于线程变量ThreadLocal的介绍以及说明. 关于线程变量ThreadLocal的介绍以及说明. 关于线程变量ThreadLocal的介绍以及说明. 关于线程变量ThreadLocal的介绍以及说明. ...