java多线程模式ThreadLocal原理简述及其使用详解

114 篇文章 0 订阅
3 篇文章 0 订阅

原创整理不易,转载请注明出处:java多线程模式ThreadLocal原理简述及其使用详解

代码下载地址:http://www.zuidaima.com/share/1781557457128448.htm

ThreadLocal是为了使每个线程保存一份属于自己的数据。
先看一个使用ThreadLocal的实例。

 package com.zuidaima.aop.framework;

 import com.zuidaima.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,那么这个代理对象在创建后,就要一层层传递下去,才能在后面获取到并使用。
通过这个例子,我们可以知道[b]ThreadLocal主要是提供了一种保持对象的方法以及避免了对象在程序调用中传递的简便访问方法。ThreadLocal与共享数据和同步没有明显关系。[/b]

下面看看相关的源码以了解具体的结构。

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时引用了同一个数据,仍然存在同步问题。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值