java多线程模式ThreadLocal原理简述及其使用详解
2016-04-23 09:58
776 查看
原文:java多线程模式ThreadLocal原理简述及其使用详解
源代码下载地址:http://www.zuidaima.com/share/1781557457128448.htm
ThreadLocal是为了使每个线程保存一份属于自己的数据。
先看一个使用ThreadLocal的实例。
package org.springframework.aop.framework; import org.springframework.core.NamedThreadLocal; public abstract class AopContext { private static final ThreadLocal <Object> currentProxy= new NamedThreadLocal <Object> ( " Current AOP proxy " ); public static Object currentProxy() throws IllegalStateException { Object proxy= currentProxy.get(); if (proxy== null ) { throw new IllegalStateException( " Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available. " ); } return proxy; } static Object setCurrentProxy(Object proxy) { Object old= currentProxy.get(); if (proxy != null ) { currentProxy.set(proxy); } else { currentProxy.remove(); } return old; } }
上例展示的是spring框架中获取当前线程的代理对象的方法,AopContext.currentProxy(),在本线程的程序调用栈中只要调用AopContext的静态方法就可以获取本线程相关的代理对象。如果不用ThreadLocal,那么这个代理对象在创建后,就要一层层传递下去,才能在后面获取到并使用。
通过这个例子,我们可以知道ThreadLocal主要是提供了一种保持对象的方法以及避免了对象在程序调用中传递的简便访问方法。ThreadLocal与共享数据和同步没有明显关系。
下面看看相关的源码以了解具体的结构。
public class Thread implements Runnable { // ThreadLocalMap是一个以ThreadLocal为key,Object为值的map,由ThreadLocal维护 ThreadLocal.ThreadLocalMap threadLocals= null ; }
从Thread的源码中可以得知,是每一个Thread持有一个自己的map,并不是一个ThreadLocal持有一个map。
public class ThreadLocal <T> { public T get() { // 获取当前线程 Thread t= Thread.currentThread(); // 获取当前线程的threadLocals变量 ThreadLocalMap map= getMap(t); // 从当前线程的threadLocals变量中取得本threadLocal为key的值 if (map != null ) { ThreadLocalMap.Entry e= map.getEntry( this ); if (e != null ) return (T)e.value; } return setInitialValue(); } private T setInitialValue() { T value= initialValue(); Thread t= Thread.currentThread(); ThreadLocalMap map= getMap(t); if (map != null ) map.set( this , value); else createMap(t, value); return value; } public void set(T value) { // 获取当前线程 Thread t= Thread.currentThread(); // 获取当前线程的threadLocals变量 ThreadLocalMap map= getMap(t); // 以本threadLocal为key的保存值到当前线程的threadLocals变量中去 if (map != null ) map.set( this , value); else createMap(t, value); } ThreadLocalMap getMap(Thread t) { return t.threadLocals; } void createMap(Thread t, T firstValue) { t.threadLocals= new ThreadLocalMap( this , firstValue); } }
使用ThreadLocal过程: 对于每一个需要线程保存自身实例的变量,需要定义一个静态的ThreadLocal实例。然后将一个共用的ThreadLocal静态实例作为key,将不同对象的引用保存到不同线程的ThreadLocalMap中,然后在线程执行的各处通过这个静态ThreadLocal实例的get()方法取得自己线程保存的那个对象。
此外,每个线程保存的自身数据并不是通过备份或复制的,而是new创建出来的。
通过ThreadLocal各个线程只能获取自身对应的数据,不能访问其他线程的数据,但是如果两个线程在set时引用了同一个数据,仍然存在同步问题。
相关文章推荐
- java的debug和release编译方式
- Eclipse 安卓开发导入SlidingMenu侧滑菜单这些坑!!
- JDK6和JDK7中的substring()
- JavaCPP项目和类库项目_JavaCV_OpenCV
- Spring事务注解@Transactional的坑爹陷阱
- Spring MVC与JAX-RS比较与分析
- spring websocket 使用@SendToUser
- springMVC控制器方法POJO入参对象是如何赋值的
- Java实现直接插入排序和折半插入排序算法示例
- selenium 对浏览器的操控 java
- Java的Struts框架中配置国际化的资源存储的要点解析
- SpringMvc 参数接收
- Java的String char()[待补充]
- Maven+Spring+邮件发送
- 【012】【Java晚期(运行期)优化】
- JVM内存划分总结
- java多线程
- Java虚拟机学习总结目录
- Java程序通用场景性能分析
- JAVA 公共方法 之 date时间处理