- 使用ThreadLocal的时候我们保证了每个线程可以隔离使用对象,避免线程间的数据干扰。
 
常用例子:
public class ThreadLocalTest {
    public static void main(String[] args) throws InterruptedException {
        ThreadLocal tl=new ThreadLocal();
        tl.set("123");
        System.out.println(Thread.currentThread()+":"+tl.get());
        
        Thread t=new Thread(
            new  Runnable() {
                public void run() {
                   tl.set("456"); 
                   System.out.println(Thread.currentThread()+":"+tl.get());
                }
            });
        t.start();
        Thread.sleep(1000);
        System.out.println(Thread.currentThread()+":"+tl.get());
}}
结果:
Thread[main,5,main]:123
Thread[Thread-0,5,main]:456
Thread[main,5,main]:123
从上面的例子可以看出来,每个线程保存的对象是隔离的!
代码分析
下面是Thread里面定义的对象,它的声明是在ThreadLocal里面的一个静态子类对象 ThreadLocal.ThreadLocalMap threadLocals = null;
这里是ThreadLocal的对象定义 static class ThreadLocalMap { static class Entry extends WeakReference<ThreadLocal>> { /** The value associated with this ThreadLocal. */ Object value; //可以看出key为当前的ThreadLocal对象,value为保存的数据对象 Entry(ThreadLocal> k, Object v) { super(k); value = v; } } }
下面set/get/getMap/createMap方法,可以存储数据
public void set(T value) {
        //获取当前线程
        Thread t = Thread.currentThread();
        //根据当前的线程获取数据
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
    
public T get() {
       //获取当前线程
        Thread t = Thread.currentThread();
        //根据当前的线程获取数据
        ThreadLocalMap map = getMap(t);
        if (map != null) {
        //这里依据对象获取保存的数据
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }    
    
    /**
     * 这里可以看出返回的数据是当前的线程变量
     */
 ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
  }    
  
 void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
}  
从上面可以看出写的代码示例,返回值是不同的因为线程是独立的,
独立线程会有自己的单独数据存储map,
至于ThreadLocal当作key是为了防止多个ThreadLocal在同一个线程当中做区分
ThreadLocal做保存数据的key唯一性
//ThreadLocal类中有一个被final修饰的类型为int的threadLocalHashCode,它在该ThreadLocal被构造的时候就会生成,相当于一个ThreadLocal的ID private final int threadLocalHashCode = nextHashCode(); //threadLocalHashCode值来源于这里 private static AtomicInteger nextHashCode =new AtomicInteger(); private static final int HASH_INCREMENT = 0x61c88647; private static int nextHashCode() { return nextHashCode.getAndAdd(HASH_INCREMENT); }
 
 
 
 