ThreadLocal源碼分析

最近查看Android,Looper源碼的時(shí)候,看到一個(gè)這樣的寫(xiě)法

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

給我的第一印象是:
1.比較懶的一種單例的寫(xiě)法娶耍。
2.跟線程有很大的關(guān)系朴爬。不然怎么會(huì)叫做ThreadLocal呢局待?
3.覺(jué)得是一種集合,因?yàn)樘峁┝薵et/set方法。 但是本身是單例机断,那么get出來(lái)不是同一個(gè)值嗎?那不就是沒(méi)有意義了嗎材部?帶著這些問(wèn)題查看了一下源碼毫缆。

public class ThreadLocal<T> {

    /* Thanks to Josh Bloch and Doug Lea for code reviews and impl advice. */

    /**
     * Creates a new thread-local variable.
     */
    public ThreadLocal() {}

    /**
     * Returns the value of this variable for the current thread. If an entry
     * doesn't yet exist for this variable on this thread, this method will
     * create an entry, populating the value with the result of
     * {@link #initialValue()}.
     *
     * @return the current value of the variable for the calling thread.
     */
    @SuppressWarnings("unchecked")
    public T get() {
        // Optimized for the fast path.
        Thread currentThread = Thread.currentThread();
        Values values = values(currentThread);
        if (values != null) {
            Object[] table = values.table;
            int index = hash & values.mask;
            if (this.reference == table[index]) {
                return (T) table[index + 1];
            }
        } else {
            values = initializeValues(currentThread);
        }

        return (T) values.getAfterMiss(this);
    }

    /**
     * Provides the initial value of this variable for the current thread.
     * The default implementation returns {@code null}.
     *
     * @return the initial value of the variable.
     */
    protected T initialValue() {
        return null;
    }

    /**
     * Sets the value of this variable for the current thread. If set to
     * {@code null}, the value will be set to null and the underlying entry will
     * still be present.
     *
     * @param value the new value of the variable for the caller thread.
     */
    public void set(T value) {
        Thread currentThread = Thread.currentThread();
        Values values = values(currentThread);
        if (values == null) {
            values = initializeValues(currentThread);
        }
        values.put(this, value);
    }

    /**
     * Removes the entry for this variable in the current thread. If this call
     * is followed by a {@link #get()} before a {@link #set},
     * {@code #get()} will call {@link #initialValue()} and create a new
     * entry with the resulting value.
     *
     * @since 1.5
     */
    public void remove() {
        Thread currentThread = Thread.currentThread();
        Values values = values(currentThread);
        if (values != null) {
            values.remove(this);
        }
    }

    /**
     * Creates Values instance for this thread and variable type.
     */
    Values initializeValues(Thread current) {
        return current.localValues = new Values();
    }

    /**
     * Gets Values instance for this thread and variable type.
     */
    Values values(Thread current) {
        return current.localValues;
    }

    /** Weak reference to this thread local instance. */
    private final Reference<ThreadLocal<T>> reference
            = new WeakReference<ThreadLocal<T>>(this);

    /** Hash counter. */
    private static AtomicInteger hashCounter = new AtomicInteger(0);

    /**
     * Internal hash. We deliberately don't bother with #hashCode().
     * Hashes must be even. This ensures that the result of
     * (hash & (table.length - 1)) points to a key and not a value.
     *
     * We increment by Doug Lea's Magic Number(TM) (*2 since keys are in
     * every other bucket) to help prevent clustering.
     */
    private final int hash = hashCounter.getAndAdd(0x61c88647 * 2);

    /**
     * Per-thread map of ThreadLocal instances to values.
     */

代碼比較多,但是我們挑比較關(guān)鍵的地方看( set/get)
get:獲取當(dāng)前線程的localValues,如果是null的話,initializeValues一個(gè)localValues乐导。然后從localValues中獲取值苦丁。
set:獲取當(dāng)前線程的localValues,如果是null的話,initializeValues一個(gè)localValues。然后把值放入當(dāng)前線程中物臂。

  1. ThreadLocal本身并沒(méi)有存儲(chǔ)數(shù)據(jù)的能力旺拉,真正存儲(chǔ)數(shù)據(jù)的地方是存儲(chǔ)在當(dāng)前線程中。
  2. 每一個(gè)線程localValues是不同的棵磷。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蛾狗,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子仪媒,更是在濱河造成了極大的恐慌沉桌,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件算吩,死亡現(xiàn)場(chǎng)離奇詭異留凭,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)偎巢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門蔼夜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人压昼,你說(shuō)我怎么就攤上這事求冷。” “怎么了窍霞?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵匠题,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我官撼,道長(zhǎng)梧躺,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮掠哥,結(jié)果婚禮上巩踏,老公的妹妹穿的比我還像新娘。我一直安慰自己续搀,他們只是感情好塞琼,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著禁舷,像睡著了一般彪杉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上牵咙,一...
    開(kāi)封第一講書(shū)人閱讀 52,457評(píng)論 1 311
  • 那天派近,我揣著相機(jī)與錄音,去河邊找鬼洁桌。 笑死渴丸,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的另凌。 我是一名探鬼主播谱轨,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼吠谢!你這毒婦竟也來(lái)了土童?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤工坊,失蹤者是張志新(化名)和其女友劉穎献汗,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體王污,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡雀瓢,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了玉掸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡醒叁,死狀恐怖司浪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情把沼,我是刑警寧澤啊易,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站饮睬,受9級(jí)特大地震影響租谈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一割去、第九天 我趴在偏房一處隱蔽的房頂上張望窟却。 院中可真熱鬧,春花似錦呻逆、人聲如沸夸赫。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)茬腿。三九已至,卻和暖如春宜雀,著一層夾襖步出監(jiān)牢的瞬間切平,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工辐董, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留悴品,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓郎哭,卻偏偏與公主長(zhǎng)得像他匪,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子夸研,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容