Java---ThreadLocal的用法与理解实现

标签: 线程ThreadLocaapijava2016-08-14 14:23 4723人阅读 评论(1) 收藏 举报 分类: ❷ Java大学之行(207) ----- ③、Java知识点及应用(34) 版权声明:本文为谙忆原创文章,转载请附上本文链接,谢谢。Java.lang 类 ThreadLocal 我们可以称ThreadLocal为:线程本地变量官方API是这样介绍的: 该类提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。ThreadLocal 实例通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。我们直接new 就可以构造一个 ThreadLocal对象。 它只有4个方法: T get() 返回此线程局部变量的当前线程副本中的值。 protected T initialValue() 返回此线程局部变量的当前线程的“初始值”。 void remove() 移除此线程局部变量当前线程的值。 void set(T value) 将此线程局部变量的当前线程副本中的值设置为指定值。 1234567812345678initialValue这个方法是一个延迟调用方法(可以理解成给初始值),在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null。 如果程序员希望线程局部变量具有 null 以外的值,则必须为 ThreadLocal 创建子类,并重写此方法。通常将使用匿名内部类完成此操作。通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值  private static ThreadLocal t= new ThreadLocal(){   public Integer initialValue() {   return 0;   }  };123456123456ThreadLocal是这样做到为每一个线程维护变量的: 在ThreadLocal类中有一个Map,用于存储每一个线程与线程变量的值,Map中元素的键为线程对象,而值对应线程的变量值。 我们自己就可以写出一个简单的实现版本:package cn.hncu;import java.util.HashMap;import java.util.Map;public class MyThreadLocle { private Map map = new HashMap(); public Object get(){ Thread curThread = Thread.currentThread(); Object value = map.get(curThread); return value; } public void set(Object obj){ Thread curThread = Thread.currentThread(); map.put(curThread, obj); }}12345678910111213141516171819201234567891011121314151617181920现在我们用一个实例来加深对ThreadLocal的理解:package cn.hncu;import java.util.Random;import org.junit.Test;public class ThreadLocalDemo { private static ThreadLocalt1 = new ThreadLocal(); public static Object getValue(){ Object o = t1.get(); //不用给key,因为t1内部会自动获取当前线程的thread对象,并以上作为key到它的池中去取obj if(o==null){ System.out.println("空的"); Random r = new Random(); o = r.nextInt(1000); t1.set(o); } return o; } @Test public void test(){ Object obj = getValue(); Object obj2 = getValue();//第二次去拿,不是空的了 System.out.println(obj+","+obj2); System.out.println(obj==obj2);//true A a = new A(); Object obj3 = a.getValue(); System.out.println(obj==obj3);//true B b = new B(); final Object obj4 = b.getValue(); System.out.println(obj3==obj4);//true //由上面的例子可以知道,只要是同一个线程,不管是哪个类,从ThreadLocal中get的对象都是同一个 System.out.println("---====不同的线程====---"); new Thread() { @Override public void run() { A a = new A(); Object obj5 = a.getValue(); System.out.println("obj5:"+obj5); B b = new B(); Object obj6 = b.getValue(); System.out.println("obj6:"+obj6); System.out.println("obj5=obj6:"+(obj5==obj6)); System.out.println("obj4=obj5:"+(obj4==obj5)); } }.start(); }}class A{ public Object getValue(){ Object obj = ThreadLocalDemo.getValue(); System.out.println("A:"+obj); return obj; }}class B{ public Object getValue(){ Object obj = ThreadLocalDemo.getValue(); System.out.println("B:"+obj); return obj; }}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727312345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273通过上面那个实例我们可以知道: 各个线程中访问的是不同的对象。通过ThreadLocal.set()将这个新创建的对象的引用保存到各线程的自己的一个map中,每个线程都有这样一个map,执行ThreadLocal.get()时,各线程从自己的map中取出放进去的对象,因此取出来的是各自自己线程中的对象,ThreadLocal实例是作为map的key来使用的。看下jdk1.7的部分ThreadLocal类源码: get()与set()方法:/** * Returns the value in the current thread's copy of this * thread-local variable. If the variable has no value for the * current thread, it is first initialized to the value returned * by an invocation of the {@link #initialValue} method. * * @return the current thread's value of this thread-local */public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) return (T)e.value; } return setInitialValue(); }/** * Sets the current thread's copy of this thread-local variable * to the specified value. Most subclasses will have no need to * override this method, relying solely on the {@link #initialValue} * method to set the values of thread-locals. * * @param value the value to be stored in the current thread's copy of * this thread-local. */ public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }123456789101112131415161718192021222324252627282930313233343536123456789101112131415161718192021222324252627282930313233343536转载请附上原文链接: http://blog.csdn.net/qq_26525215/article/details/52204097
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值