說好的技術博客,現在就來第一篇
最近一段時間在把一個本地工具搭成web版本,進行一些封裝,針對一些業務功能還要進行在開發。用到一些并發模型,涉及一點線程。陸陸續續會更新編寫過程中遇到、用到、學到的東西。
這篇主要說一下ThreadLocal。
網上有很多ThreadLocal的使用教程,也都提到ThreadLocal為每個使用該變量的線程提供獨立的變量副本,而不會影響到其他線程。講到實現原理的時候,都提到說:
JDK中ThreadLocal類中有一個Map,key是線程對象,valute為對應線程的變量副本。
我想說,這是完全錯誤的。。。
其實,從JDK1.2版本開始,ThreadLocal的實現原理就不是這樣的。
真實的情況是,每一個Thread內,都會有一個ThreadLocalMap用來存放自己用到的ThreadLocal,key為ThreadLocal實例,value為使用時set進去的對象。
我們從源碼的角度來分析(使用jdk1.7版本)
首先來看ThreadLocal的set方法
java.lang.ThreadLocal public void set(T value) { Thread t = Thread.currentThread();//取到當前線程,native方法 ThreadLocalMap map = getMap(t);//我想誤解應該是從這句開始的,后面會詳細說 if (map != null) map.set(this, value);//key為ThreadLocal,value為set進來的對象 else createMap(t, value); }
乍一看是通過當前線程t取到了ThreadLocalMap,其實是從t中取到ThreadLocalMap對象,我們看一眼getMap(t)方法的實現就清楚了。
java.lang.ThreadLocal ThreadLocalMap getMap(Thread t) { return t.threadLocals; }
java.lang.Thread ThreadLocal.ThreadLocalMap threadLocals = null;
這就是ThreadLocal為什么會是每個線程單獨擁有的。
在每個Thread中會有一個ThreadLocalMap,當我們調用某一個ThreaLocal實例的set方法時,會去當前Thread中取ThreadLocalMap,使用ThreadLocal實例為key,將set進來的值作為value存儲在map中。
The end
另附createMap方法
java.lang.ThreadLocal void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }
PS:ThreadLocalMap也挺有意思,他是一個被標示為static的內部類,核心是Entry[],Entry也為static,繼承自WeakReference<ThreadLocal>。