1. 程式人生 > >ThreadLocal理解-結合連線池

ThreadLocal理解-結合連線池

本想看看部落格理解下ThreadLocal,看了幾篇看的似懂非懂,還看出一堆疑問。從很多部落格中也看出了Thread感覺沒表面那麼簡單,但是表述貌似也不好。

ThreadLocal和Thread關係

先來圖說話(說半天原始碼真不如來張圖)

這裡寫圖片描述

上面圖描述Thread和ThreadLocal之間的關係,從此就能得出很多基礎結論了:

  • 執行緒內部持有一個Map存放著自己的區域性變數,這些變數的key是ThreadLocal物件(可以理解為什麼叫做執行緒區域性變量了吧);
  • 有一個變數想放入執行緒的區域性變數的你就需要建立一個ThreadLocal物件;
  • ThreadLocal本身沒有什麼儲存結構,只是提供了方法,所以變數不是存在ThreadLocal中的,ThreadLocal負責搬運。

原始碼:

就兩個重要方法:

set方法

    public void set(T value) {
        //獲取當前執行緒,然後獲取到當前執行緒裡面的ThreadLocalMap引用,
        //判斷當前執行緒裡面是建立該Map物件,有則直接set,沒有就初始化一個Map,再將值放入。
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value
);// 以ThreadLocal物件為key 傳入value為value else createMap(t, value); }

get方法

    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        //存在Map就找到當前執行緒Map中該ThreadLocal物件的value
        if (map != null) {
            ThreadLocalMap.
Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } //沒有就初始化它 return setInitialValue(); }

ThreadLocal不是用來解決物件共享訪問問題的,而主要是提供了執行緒保持物件的方法和避免參數傳遞的方便的物件訪問方式 (網上一段話,我沒看明白,但是我知道作者想表達的get到的那個點,並且很有道理的樣子)連線:文章

先理清下ThreadLocal的作用到底是什麼?

它並不是為了自帶了執行緒安全,併發控制這些機制,它是通過犧牲空間(建立額外更多的物件來),它的目的僅僅就是為了讓執行緒使用自己的變數。—讓同一個執行緒上的所有程式碼塊都是使用的該變數。
就拿資料庫連線來說,如果沒有使用ThreadLocal,那麼勢必我們會定義的一個數據庫Connection,然後所有的執行緒共享它!但是這樣是執行緒不安全的(connection控制著事物,會導致事物混亂)!那麼我們就需要同步,但是同步是很耗效能的。所以使用ThreadLocal,可以理解為為每一個執行緒都建立一個Connection物件(當然實際不會這樣)。這個Conncetion物件只被該執行緒使用。–所以,不是說有一個共享變數我們為了讓他執行緒安全就將該變數放入ThreadLocal中就安全了,這樣其實還是不安全的因為引用傳遞,ThreadLocal做法是為每個執行緒建立一個物件。
這本身就是一種空間換時間的機制,沒有什麼屌的優化機制在裡面。

那你或許又問 這有什麼用?
空間換時間– 我們不需要使用同步塊了,執行緒的區域性中存的每個物件都是不一樣的,所以不會有執行緒安全問題。所以之前不理解的將一個變數引用傳入到ThreadLocal中這種場景本身對於ThreadLocal來講沒有意義,也就是說ThreadLocal不是用來幹這個的(看了好多部落格寫著的意思就是講一個Connection放入到ThreadLocal中就執行緒安全了?開玩笑!)

連線池的應用

第一次接觸這個就是因為連線池

始終記得:

ThreadLocal 將一些執行緒不安全的變數,將用同步的方式轉為為每個執行緒建立一個物件來實現執行緒安全。

文章也是自己理解的,可能有不對的地方,請指正。