ThreadLocal源码解析
synchronized这类线程同步的机制可以解决多线程并发问题,在这种解决方案下,多个线程访问到的,都是同一份变量的内容。为了防止在多线程访问的过程中,可能会出现的并发错误。不得不对多个线程的访问进行同步,这样也就意味着,多个线程必须先后对变量的值进行访问或者修改,这是一种以延长访问时间来换取线程安全性的策略。
而ThreadLocal类为每一个线程都维护了自己独有的变量拷贝。每个线程都拥有了自己独立的一个变量,竞争条件被彻底消除了,那就没有任何必要对这些线程进行同步,它们也能最大限度的由CPU调度,并发执行。并且由于每个线程在访问该变量时,读取和修改的,都是自己独有的那一份变量拷贝,变量被彻底封闭在每个访问的线程中,并发错误出现的可能也完全消除了。对比前一种方案,这是一种以空间来换取线程安全性的策略。
ThreadLocal允许每个线程与持有数值的对象关联在一起,ThreadLocal提供了get和set方法,为每个使用它的线程提供了维护一份单独的拷贝。所以get总是返回当前线程通过set获取到的最新值.
ThreadLocal的实现原理为内部创建了一个静态内部类,它是用来存放ThreadLocal及其关联值的集合。
static class ThreadLocalMap
在ThreadLocalMap中又含有一个静态内部类Entry,并有一个私有变量 private Entry[] table;用来存储Entry类
/** *Entry类用来存储ThreadLocal以及其关联的value. *该类继承了WeakReference<ThreadLocal>,表示一旦没有指向key(ThreadLocal)的强引用,Entry类会被立即回收 */ static class Entry extends WeakReference<ThreadLocal> { /** 值和ThreadLocal相关联. */ Object value; Entry(ThreadLocal k, Object v) { super(k); value = v; } }
在ThreadLocal中主要有get()和set两个方法,其中set方法是设置当前线程ThreadLocal对应的值,其源码为
public void set(T value) { Thread t = Thread.currentThread();//获取当前运行的线程 ThreadLocalMap map = getMap(t); //获取当前线程中ThreadMap if (map != null) //如果map不为空则将ThreadLocal及value添加到map中 map.set(this, value); else createMap(t, value); //如果map为空,创建新的map,并ThreadLocal及value添加到map中 }
通过查看Thread类的源码可知,Thread类中含有成员ThreadLocalMap,通过调用getMap(t)方法,可以获取当前执行线程中的ThreadLocalMap成员。
1 /* ThreadLocal values pertaining to this thread. This map is maintained 2 * by the ThreadLocal class. */ 3 ThreadLocal.ThreadLocalMap threadLocals = null;
1 /** 2 * Get the map associated with a ThreadLocal. Overridden in 3 * InheritableThreadLocal. 4 * 5 * @param t the current thread 6 * @return the map 7 */ 8 ThreadLocalMap getMap(Thread t) { 9 return t.threadLocals; 10 }
ThreadLocal中的get()方法主要用来获取当前执行线程中ThreadLocal对应的值,源码为:
1 /** 2 * Returns the value in the current thread's copy of this 3 * thread-local variable. If the variable has no value for the 4 * current thread, it is first initialized to the value returned 5 * by an invocation of the {@link #initialValue} method. 6 * 7 * @return the current thread's value of this thread-local 8 */ 9 public T get() { 10 //获取当前线程 11 Thread t = Thread.currentThread(); 12 13 /**仍然通过getMap方法来获取当前线程中存储Threadlocal及其关联值集合*/ 14 ThreadLocalMap map = getMap(t); 15 if (map != null) { 16 ThreadLocalMap.Entry e = map.getEntry(this); 17 if (e != null) 18 return (T)e.value;//如果不为空则返回当前值 19 } 20 //如果为空则返回ThreadLocal初始化的值 21 return setInitialValue(); 22 }

浙公网安备 33010602011771号