ThreadLocal與局部變數__局部變數

來源:互聯網
上載者:User

ThreadLocal和線程局部變數有什麼區別,我們先看一段代碼,如下:

public class ThreadLocalLearn {    static ThreadLocal<IntHolder> tl = new ThreadLocal<IntHolder>(){        protected IntHolder initialValue() {            return new IntHolder();        }    };    public static void main(String args[]) {        for(int i=0; i<5; i++) {            Thread th = new Thread(new ThreadTest(tl, i));            th.start();        }    }}class ThreadTest implements Runnable{    ThreadLocal<IntHolder> tl ; //threadlocal變數    int i;    int a = 3; //線程局部變數    public ThreadTest(ThreadLocal<IntHolder> tl, int i) {        super();        this.tl = tl;        this.i = i;    }    @Override    public void run() {        tl.get().increAndGet();        a++;        System.out.println(tl.get().getA() + " ");        System.out.println("a : " + a);    }}class IntHolder{    int a = 1;    public int getA() {        return a;    }    public void setA(int a) {        this.a = a;    }    public int increAndGet() {        return ++a;    }}

代碼的運行結果如下:

2 a : 42 a : 42 a : 42 a : 42 a : 4

可以看到,局部變數和ThreadLocal起到的作用是一樣的,保證了並發環境下資料的安全性。那就是說,完全可以用局部變數來代替ThreadLocal咯,這樣想法對麼。我們看一看官方對於ThreadLocal的描述:

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its {@code get} or {@code set} method) has its own, independently initialized copy of the variable. {@code ThreadLocal} instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).

翻譯起來就是

ThreadLocal提供的是一種線程局部變數。這些變數不同於其它變數的點在於每個線程在擷取變數的時候,都擁有它自己相對獨立的變數初始化拷貝。ThreadL:ocal的執行個體一般是私人靜態,可以做到與一個線程綁定某一種狀態。PS:有更好的翻譯請指教。

      所以就這段話而言,我們知道ThreadLocal不是為了滿足多安全執行緒而開發出來的,因為局部變數已經足夠安全。ThreadLocal是為了方便線程處理自己的某種狀態。
      可以看到ThreadLocal執行個體化所處的位置,是一個線程共有地區。好比一個銀行和個人,我們可以把錢存在銀行,也可以把錢存在家。存在家裡的錢是局部變數,僅供個人使用;存在銀行裡的錢也不是說可以讓別人隨便使用,只有我們以個人身份去擷取才能得到。所以說ThreadLocal封裝的變數我們是在外面某個地區儲存了處於我們個人的一個狀態,只允許我們自己去訪問和修改的狀態。
      ThreadLocal同時提供了初始化的機制,在執行個體化時重寫initialValue()方法,便可實現變數的初始化工作

    //method 1    static ThreadLocal<IntHolder> tl = new ThreadLocal<IntHolder>(){        protected IntHolder initialValue() {            return new IntHolder();        }    };    //method 2    IntHolder  intHolder = new IntHolder();    static ThreadLocal<IntHolder> tl = new ThreadLocal<IntHolder>(){        protected IntHolder initialValue() {            return intHolder;        }    };

      方法一和方法二都可以實現初始化工作,但是方法二不能保證線程變數的安全性,因為引用拷貝指向的是同一個執行個體,對引用拷貝的修改,等同於對執行個體的修改。


      當然,也可以在判斷ThreadlLocal擷取資料為空白時,線上程內部為ThreadLocal執行個體化一個資料。如下:

if(null == tl.get()) {    tl.set(new IntHolder());}

      為什麼我們需要ThreadLocal來實現在自身內部外建立一個有關自己的狀態呢。其實可以完全使用參數傳遞內部參數,就像我在自己隨便放錢一樣。這裡要注意的是,我們定義一個方法的時候,並不是參數越多越好,有些共有參數,我們應該盡量設為全域,便於系統的可維護性與可擴充性。另一個角度考慮,銀行也有其存在的價值,ThreadLocal會簡化我們的編程,畢竟它是安全的。

根據ThreadLocal原理,我們自己實現一個:

import java.util.concurrent.ConcurrentHashMap;public class ThreadLocalVar<T> {    public T initVaribale() {        return null;    }    volatile ConcurrentHashMap<Thread, T> map = new ConcurrentHashMap<Thread, T>();     public void put(T t) {        map.put(Thread.currentThread(), t);    }    public T get() {        T value = map.get(Thread.currentThread());        if(null == value) {            T t = initVaribale();            if(null == t) {                return null;            }            map.put(Thread.currentThread(), t);            return t;        } else {            return value;        }    }}

有興趣也可以去閱讀jdk中ThreadLocal的源碼~

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.