一.ThreadLocal
Thread中有一个ThreadLocalMap类型的属性,threadLocals:
<span style="color:#f8f8f2"><code class="language-java">ThreadLocal<span style="color:#f8f8f2">.</span>ThreadLocalMap threadLocals <span style="color:#f8f8f2">=</span> <span style="color:#f92672">null</span><span style="color:#f8f8f2">;</span></code></span>
ThreadLocal的 set() 方法:拿到当前线程的 threadLocals,然后往其中塞值,key是ThreadLocal本身,value是塞入的值。
取出Map的时候,如果为空,则初始化Map。
<span style="color:#333333"><span style="color:#f8f8f2"><code class="language-java"> <span style="color:#66d9ef"><span style="color:#f92672">public</span></span> <span style="color:#66d9ef"><span style="color:#f92672">void</span></span> <span style="color:#e6db74"><span style="color:#a6e22e">set</span></span><span style="color:#f8f8f2"><span style="color:#f8f8f2">(</span></span><span style="color:#f8f8f2">T value</span><span style="color:#f8f8f2"><span style="color:#f8f8f2">)</span></span> <span style="color:#f8f8f2">{</span>
Thread t <span style="color:#f8f8f2">=</span> Thread<span style="color:#f8f8f2">.</span><span style="color:#e6db74">currentThread</span><span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">;</span>
ThreadLocalMap map <span style="color:#f8f8f2">=</span> <span style="color:#e6db74">getMap</span><span style="color:#f8f8f2">(</span>t<span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">;</span>
<span style="color:#66d9ef"><span style="color:#f92672">if</span></span> <span style="color:#f8f8f2">(</span>map <span style="color:#f8f8f2">!=</span> <span style="color:#f92672">null</span><span style="color:#f8f8f2">)</span>
map<span style="color:#f8f8f2">.</span><span style="color:#e6db74">set</span><span style="color:#f8f8f2">(</span><span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">,</span> value<span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">;</span>
<span style="color:#66d9ef"><span style="color:#f92672">else</span></span>
<span style="color:#e6db74">createMap</span><span style="color:#f8f8f2">(</span>t<span style="color:#f8f8f2">,</span> value<span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">;</span>
<span style="color:#f8f8f2">}</span>
ThreadLocalMap <span style="color:#e6db74"><span style="color:#a6e22e">getMap</span></span><span style="color:#f8f8f2"><span style="color:#f8f8f2">(</span></span><span style="color:#f8f8f2">Thread t</span><span style="color:#f8f8f2"><span style="color:#f8f8f2">)</span></span> <span style="color:#f8f8f2">{</span>
<span style="color:#66d9ef"><span style="color:#f92672">return</span></span> t<span style="color:#f8f8f2">.</span>threadLocals<span style="color:#f8f8f2">;</span>
<span style="color:#f8f8f2">}</span>
<span style="color:#66d9ef"><span style="color:#f92672">void</span></span> <span style="color:#e6db74"><span style="color:#a6e22e">createMap</span></span><span style="color:#f8f8f2"><span style="color:#f8f8f2">(</span></span><span style="color:#f8f8f2">Thread t</span><span style="color:#f8f8f2"><span style="color:#f8f8f2">,</span></span><span style="color:#f8f8f2"> T firstValue</span><span style="color:#f8f8f2"><span style="color:#f8f8f2">)</span></span> <span style="color:#f8f8f2">{</span>
t<span style="color:#f8f8f2">.</span>threadLocals <span style="color:#f8f8f2">=</span> <span style="color:#66d9ef"><span style="color:#f92672">new</span></span> ThreadLocalMap<span style="color:#f8f8f2">(</span><span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">,</span> firstValue<span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">;</span>
<span style="color:#f8f8f2">}</span></code></span></span>
ThreadLocal的 get() 方法:从线程中拿出threadLocals,如果不为空,从map中拿出键值对。如果Map为空或者没有拿到值,则直接返回null。
<span style="color:#333333"><span style="color:#f8f8f2"><code class="language-java"> <span style="color:#66d9ef"><span style="color:#f92672">public</span></span> T <span style="color:#e6db74"><span style="color:#a6e22e">get</span></span><span style="color:#f8f8f2"><span style="color:#f8f8f2">(</span></span><span style="color:#f8f8f2"><span style="color:#f8f8f2">)</span></span> <span style="color:#f8f8f2">{</span>
Thread t <span style="color:#f8f8f2">=</span> Thread<span style="color:#f8f8f2">.</span><span style="color:#e6db74">currentThread</span><span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">;</span>
ThreadLocalMap map <span style="color:#f8f8f2">=</span> <span style="color:#e6db74">getMap</span><span style="color:#f8f8f2">(</span>t<span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">;</span><span style="color:slategray"><span style="color:#75715e">// getMap方法,被InheritableThreadLocal重写了</span></span>
<span style="color:#66d9ef"><span style="color:#f92672">if</span></span> <span style="color:#f8f8f2">(</span>map <span style="color:#f8f8f2">!=</span> <span style="color:#f92672">null</span><span style="color:#f8f8f2">)</span> <span style="color:#f8f8f2">{</span>
ThreadLocalMap<span style="color:#f8f8f2">.</span>Entry e <span style="color:#f8f8f2">=</span> map<span style="color:#f8f8f2">.</span><span style="color:#e6db74">getEntry</span><span style="color:#f8f8f2">(</span><span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">;</span>
<span style="color:#66d9ef"><span style="color:#f92672">if</span></span> <span style="color:#f8f8f2">(</span>e <span style="color:#f8f8f2">!=</span> <span style="color:#f92672">null</span><span style="color:#f8f8f2">)</span> <span style="color:#f8f8f2">{</span>
<span style="color:#75715e">@</span><span style="color:#e6db74"><span style="color:#75715e">SuppressWarnings</span></span><span style="color:#f8f8f2">(</span><span style="color:#a6e22e"><span style="color:#e6db74">"unchecked"</span></span><span style="color:#f8f8f2">)</span>
T result <span style="color:#f8f8f2">=</span> <span style="color:#f8f8f2">(</span>T<span style="color:#f8f8f2">)</span>e<span style="color:#f8f8f2">.</span>value<span style="color:#f8f8f2">;</span>
<span style="color:#66d9ef"><span style="color:#f92672">return</span></span> result<span style="color:#f8f8f2">;</span>
<span style="color:#f8f8f2">}</span>
<span style="color:#f8f8f2">}</span>
<span style="color:#66d9ef"><span style="color:#f92672">return</span></span> <span style="color:#e6db74">setInitialValue</span><span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">;</span><span style="color:slategray"><span style="color:#75715e">// map为空 or 没有取到值</span></span>
<span style="color:#f8f8f2">}</span>
<span style="color:#66d9ef"><span style="color:#f92672">private</span></span> T <span style="color:#e6db74"><span style="color:#a6e22e">setInitialValue</span></span><span style="color:#f8f8f2"><span style="color:#f8f8f2">(</span></span><span style="color:#f8f8f2"><span style="color:#f8f8f2">)</span></span> <span style="color:#f8f8f2">{</span>
T value <span style="color:#f8f8f2">=</span> <span style="color:#e6db74">initialValue</span><span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">;</span>
Thread t <span style="color:#f8f8f2">=</span> Thread<span style="color:#f8f8f2">.</span><span style="color:#e6db74">currentThread</span><span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">;</span>
ThreadLocalMap map <span style="color:#f8f8f2">=</span> <span style="color:#e6db74">getMap</span><span style="color:#f8f8f2">(</span>t<span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">;</span>
<span style="color:#66d9ef"><span style="color:#f92672">if</span></span> <span style="color:#f8f8f2">(</span>map <span style="color:#f8f8f2">!=</span> <span style="color:#f92672">null</span><span style="color:#f8f8f2">)</span>
map<span style="color:#f8f8f2">.</span><span style="color:#e6db74">set</span><span style="color:#f8f8f2">(</span><span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">,</span> value<span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">;</span>
<span style="color:#66d9ef"><span style="color:#f92672">else</span></span>
<span style="color:#e6db74">createMap</span><span style="color:#f8f8f2">(</span>t<span style="color:#f8f8f2">,</span> value<span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">;</span>
<span style="color:#66d9ef"><span style="color:#f92672">return</span></span> value<span style="color:#f8f8f2">;</span>
<span style="color:#f8f8f2">}</span>
<span style="color:#66d9ef"><span style="color:#f92672">protected</span></span> T <span style="color:#e6db74"><span style="color:#a6e22e">initialValue</span></span><span style="color:#f8f8f2"><span style="color:#f8f8f2">(</span></span><span style="color:#f8f8f2"><span style="color:#f8f8f2">)</span></span> <span style="color:#f8f8f2">{</span>
<span style="color:#66d9ef"><span style="color:#f92672">return</span></span> <span style="color:#f92672">null</span><span style="color:#f8f8f2">;</span>
<span style="color:#f8f8f2">}</span></code></span></span>