这次的博客带来的是关于ThreadLocal<T>的理解
什么是ThreadLocal呢?根据名称来看,ThreadLocal即线程本地的意思。另外它还是一个范型类,这个范型T,就是threadLocal.set(T)的参数,也是threadLocal.get()、threadLocal.initialValue()的返回值。
public class ThreadLocal<T> { omitted ...... }
那么ThreadLocal又是如何区分不同线程的呢?
在ThreadLocal类内,还有一个静态内部类ThreadLocalMap
// ThreadLocalMap is a customized hash map suitable only for // maintaining thread local values. static class ThreadLocalMap { static class Entry extends WeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } } omitted ...... }
这个内部类,是一个自定义的hashmap,内部Entry的构造函数需要一个ThreadLocal,以及与这个ThreadLocal关联的对象。
但是我们又会发现,ThreadLocalMap类的实例却没有在ThreadLocal中声明,而是在Thread类中
public class Thread implements Runnable { /* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ ThreadLocal.ThreadLocalMap threadLocals = null; omitted ...... }
每个Thread维护一个ThreadLocalMap映射表,这个映射表的key是ThreadLocal实例本身,value是真正需要存储的Object。
所以知道了,在ThreadLocal中并没有进行copy操作,不像以前理解的拷贝副本那样,下面举一个例子:
public class ThreadLocalTest { private static People people = new People(); private static ThreadLocal<People> threadLocal = new ThreadLocal<People>(){ public People initialValue(){ return people; } }; public static void main(String[] args) throws InterruptedException { new Thread(new Runnable() { @Override public void run() { threadLocal.get().age = 5; System.out.println("people = " + threadLocal.get() + "age = " + threadLocal.get().age); } }).start(); Thread.sleep(10); new Thread(new Runnable() { @Override public void run() { System.out.println("people = " + threadLocal.get() + "age = " + threadLocal.get().age); } }).start(); } } class People { public int age; }
这样一来,在任何一个thread中修改people对象的age,都能够在另外的一个线程中看到
打印结果:
people = thread.People@6f5ab880age = 5
people = thread.People@6f5ab880age = 5
如果将threadLocal中的initialValue()的返回值改为new People,那么才不会相互影响
private static ThreadLocal<People> threadLocal = new ThreadLocal<People>(){ public People initialValue(){ return new People(); } };
打印结果为:
people = thread.People@44bacfa2age = 5
people = thread.People@44bacfa2age = 0
当然,文章还有很多没有讲,比如如何set,不过不想继续贴源码了,到此为止