原贴地址:http://www.cnblogs.com/zhengbin/p/5674638.htmlhtml
阅读目录测试
"该类提供了线程局部(thread-local)变量。这些变量不一样于它们的普通对应物,由于访问某个变量(经过其get或set方法)的每一个线程都有本身的局部变量,它独立于变量的初始化副本。ThreadLocal实例一般是类中的private static字段,它们但愿将状态与某一个线程(例如,用户ID或事物ID)相关联。"this
防止任务在共享资源上产生冲突的第二种方式是根除对变量的共享。线程本地存储是一种自动化机制,能够为使用变量的每一个不一样的线程都建立不一样的存储。所以,若是你有5个线程都要使用变量x所表示的对象,那线程本地存储就会生成5个用于x的不一样的存储块。主要是,它们使得你能够将状态与线程关联起来。线程
每一个线程都有一个独立于其它线程的上下文来保存这个变量,一个线程的本地变量对其它线程是不可见的。设计
ThreadLocal能够给一个初始值,而每一个线程都会得到这个初始化值的一个副本,这样才能保证不一样的线程都有一份拷贝。3d
ThreadLocal不是用于解决共享变量的问题的,不是为了协调线程同步而存在,而是为了方便每一个线程处理本身的状态而引入的一个机制,就像《Thinking in Java》中描述的那样:”它们使得你能够将状态与线程关联起来。“理解这点对正确使用ThreadLocal相当重要。code
从输出的结果能够看出,五个线程处理本身的本地变量值。htm
而这个测试的结果,并无相同。这是由于实例为对象,因此初始值为一个对象的引用,那么五个线程的副本就是这个对象的引用的副本,也就是说这些引用仍是指向同一个对象,因此就出现了这种状况。对象
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 }
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 }
这里注意,ThreadLocal中是有一个Map,但这个Map不是咱们平时使用的Map,而是ThreadLocalMap,ThreadLocalMap是ThreadLocal的一个内部类,不对外使用的。当使用ThreadLocal存值时,首先是获取到当前线程对象,而后获取到当前线程本地变量Map,最后将当前使用的ThreadLocal和传入的值放到Map中,也就是说ThreadLocalMap中存的值是[ThreadLocal对象, 存放的值],这样作的好处是,每一个线程都对应一个本地变量的Map,因此一个线程能够存在多个线程本地变量。下面提供一个简单的实现版本:blog