ThreadLocal用法和實現原理


如果你定義了一個單實例的java bean,它有若干屬性,但是有一個屬性不是線程安全的,比如說HashMap。並且碰巧你並不需要在不同的線程中共享這個屬性,也就是說這個屬性不存在跨線程的意義。那么你不要sychronize這么復雜的東西,ThreadLocal將是你不錯的選擇。

舉例來說:

import java.util.HashMap;

public class TreadLocalTest {

    static ThreadLocal<HashMap> map0 = new ThreadLocal<HashMap>(){
        @Override
        protected HashMap initialValue() {
            System.out.println(Thread.currentThread().getName()+"initialValue");
            return new HashMap();
        }
    };
    public void run(){
        Thread[] runs = new Thread[3];
        for(int i=0;i<runs.length;i++){
            runs[i]=new Thread(new T1(i));
        }
        for(int i=0;i<runs.length;i++){
            runs[i].start();
        }
    }
    public static class T1 implements Runnable{
        int id;
        public T1(int id0){
            id = id0;
        }
        public void run() {
            System.out.println(Thread.currentThread().getName()+":start");
            HashMap map = map0.get();
            for(int i=0;i<10;i++){
                map.put(i, i+id*100);
                try{
                    Thread.sleep(100);
                }catch(Exception ex){
                }
            }
            System.out.println(Thread.currentThread().getName()+':'+map);
        }
    }
    /**
     * Main
     * @param args
     */
    public static void main(String[] args){
        TreadLocalTest test = new TreadLocalTest();
        test.run();
    }

}

輸出解釋;

Thread-1:start
Thread-2:start
Thread-0:start
Thread-2initialValue
Thread-1initialValue
Thread-0initialValue
Thread-1:{0=100, 1=101, 2=102, 3=103, 4=104, 5=105, 6=106, 7=107, 8=108, 9=109}
Thread-2:{0=200, 1=201, 2=202, 3=203, 4=204, 5=205, 6=206, 7=207, 8=208, 9=209}
Thread-0:{0=0, 1=1, 2=2, 3=3, 4=4, 5=5, 6=6, 7=7, 8=8, 9=9}

可以看到map0 雖然是個靜態變量,但是initialValue被調用了三次,通過debug發現,initialValue是從map0.get處發起的。而且每個線程都有自己的map,雖然他們同時執行。

進入Theadlocal代碼,可以發現如下的片段;

public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }

這說明ThreadLocal確實只有一個變量,但是它內部包含一個map,針對每個thread保留一個entry,如果對應的thread不存在則會調用initialValue。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM