Java多线程之ThreadLocal总结

原贴地址:http://www.cnblogs.com/zhengbin/p/5674638.htmlhtml

阅读目录测试

官方对ThreadLocal的描述:

  "该类提供了线程局部(thread-local)变量。这些变量不一样于它们的普通对应物,由于访问某个变量(经过其get或set方法)的每一个线程都有本身的局部变量,它独立于变量的初始化副本。ThreadLocal实例一般是类中的private static字段,它们但愿将状态与某一个线程(例如,用户ID或事物ID)相关联。"this

《Thinking in Java》中的描述:

  防止任务在共享资源上产生冲突的第二种方式是根除对变量的共享。线程本地存储是一种自动化机制,能够为使用变量的每一个不一样的线程都建立不一样的存储。所以,若是你有5个线程都要使用变量x所表示的对象,那线程本地存储就会生成5个用于x的不一样的存储块。主要是,它们使得你能够将状态与线程关联起来。线程

三个要点:

  1.每一个线程都有本身的局部变量

    每一个线程都有一个独立于其它线程的上下文来保存这个变量,一个线程的本地变量对其它线程是不可见的。设计

  2.独立于变量的初始化副本

    ThreadLocal能够给一个初始值,而每一个线程都会得到这个初始化值的一个副本,这样才能保证不一样的线程都有一份拷贝。3d

  3.状态与某一个线程相关联

    ThreadLocal不是用于解决共享变量的问题的,不是为了协调线程同步而存在,而是为了方便每一个线程处理本身的状态而引入的一个机制,就像《Thinking in  Java》中描述的那样:”它们使得你能够将状态与线程关联起来。“理解这点对正确使用ThreadLocal相当重要。code

源码举例:

  从输出的结果能够看出,五个线程处理本身的本地变量值。htm

  而这个测试的结果,并无相同。这是由于实例为对象,因此初始值为一个对象的引用,那么五个线程的副本就是这个对象的引用的副本,也就是说这些引用仍是指向同一个对象,因此就出现了这种状况。对象

ThreadLocal的接口方法:

  • void set(T value):设置当前线程的线程局部变量的值;
 
 1 public void set(T value) {
 2    Thread t = Thread.currentThread();
 3    ThreadLocalMap map = getMap(t);
 4 
 5    if (map != null)
 6      map.set(this, value);
 7   //说明线程第一次使用线程本地变量(注意这里的第一次含义)
 8    else
 9        createMap(t, value);
10 }
  • public T get():该方法返回当前线程所对应的线程局部变量;
 1 public T get() {
 2   //获取当前执行线程
 3   Thread t = Thread.currentThread();
 4   //取得当前线程的ThreadLocalMap实例
 5   ThreadLocalMap map = getMap(t);
 6   //若是map不为空,说明该线程已经有了一个ThreadLocalMap实例
 7   if (map != null) {
 8     //map中保存线程的全部的线程本地变量,咱们要去查找当前线程本地变量
 9     ThreadLocalMap.Entry e = map.getEntry(this);
10     //若是当前线程本地变量存在这个map中,则返回其对应的值
11     if (e != null)
12          return (T)e.value;
13   }
14    //若是map不存在或者map中不存在当前线程本地变量,返回初始值
15    return setInitialValue();
16 }
  • public void remove():将当前线程局部变量的值删除,目的是为了减小内存的占用,该方法是JDK 5.0新增的方法。当线程结束后,对应该线程的局部变量将被自动垃圾回收,因此显示调用该方法清除线程的局部变量并非必须的操做,但它能够加快内存回收的速度;
  • protected T initialValue():返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的,这个方法是一个延迟调用方法,在线程第1次调用get()或set(T)时才执行,而且仅执行1次。ThreadLocal中的默认实现直接返回一个null。

       这里注意,ThreadLocal中是有一个Map,但这个Map不是咱们平时使用的Map,而是ThreadLocalMap,ThreadLocalMap是ThreadLocal的一个内部类,不对外使用的。当使用ThreadLocal存值时,首先是获取到当前线程对象,而后获取到当前线程本地变量Map,最后将当前使用的ThreadLocal和传入的值放到Map中,也就是说ThreadLocalMap中存的值是[ThreadLocal对象, 存放的值]这样作的好处是,每一个线程都对应一个本地变量的Map,因此一个线程能够存在多个线程本地变量。下面提供一个简单的实现版本:blog

相关文章
相关标签/搜索