Java8 ThreadLocal類源碼 詳解__Java8

來源:互聯網
上載者:User

JDK裡有一個ThreadLocal這麼一個類,其實起這個名字不是很貼近,這個類相當於給線程設定上了一個局部變數。使得,不會因為多線程訪問同一個資源而產生多線程同步問題。

因為這個ThreadLocal類裡面放的是每個線程都擁有一個副本,線程之間彼此不會互相影響。

現在這裡筆者將會從源碼的實現角度給大家講述一下ThreadLocal實現的原理。

首先我們來看一下set()這個方法的實現。



所有的講解筆者都將以注釋的形式給出。

 public void set(T value) {     //拿到當前線程對象       Thread t = Thread.currentThread(); //拿到一個Map對象,好,那麼問題來了。這個是一個什麼樣的map對象呢?? //其實這個ThreadLocalMap對象是ThreadLocal類內部自己實現的一個類似於HashMap這樣一個類        ThreadLocalMap map = getMap(t);//如果map非空,則將當前的ThreadLocal對象和這個set()方法的參數put到這個Map裡面去,//如果沒有將其建立。        if (map != null)            map.set(this, value);        else            createMap(t, value);    }



我們可以看到ThreadLocal這個類裡面確實定義了一個ThreadLocalMap類。裡面的實現和HashMap的差不多,筆者就不點進去看了。




再一個我們點進去get()方法裡面去看以下。


public T get() {//拿到當前的線程對象        Thread t = Thread.currentThread();//拿到ThreadLocalMap對象,到了這裡我們進去getMap()方法裡面去看一下         ThreadLocalMap map = getMap(t);        if (map != null) {            ThreadLocalMap.Entry e = map.getEntry(this);            if (e != null) {                @SuppressWarnings("unchecked")                T result = (T)e.value;                return result;            }        }        return setInitialValue();    }


相比,看到了前面的解釋,  各位讀者也很想進去看一看getMap的實現。

 ThreadLocalMap getMap(Thread t) {     //從這裡可以看出 ThreadLocalMap對象是由當前的線程對象持有的,//但是維護的工作是由ThreadLocal這個類來完成的。       return t.threadLocals;    }




//createMap方法在當前線程對象內部持有的那個ThreadLocalMap對象為空白,會調用之//從這裡我們也可以看出是ThreadLocal這個類在維護這個關係void createMap(Thread t, T firstValue) {        t.threadLocals = new ThreadLocalMap(this, firstValue);    }
寫到這裡我們可以下一個結論。

ThreadLocal底層是使用一個自己實現的Map來儲存使用者set()進來的值。   那個map的鍵,即為當前的ThreadLocal對象。

有的朋友可能會問了。現在ThreadLocal只有一個對象。那麼Map裡的值還不是會被其他線程所共用。

其實這個不是的,筆者剛開始也是這麼考慮的----------->這個Map裡儲存的應該是當前的Thread對象和值。而不應該是上面那種。

其實不是的。  因為那個ThreadLocal類自己實現的Map對象是每個線程對象內部自己持有一份。所以說,每個線程對象內的ThreadLocalMap對象是不一樣的。所以,裡面的資料是不會被其他線程所共用,都是自己用自己的。

這裡筆者寫了一個demo來證明每個線程持有的ThreadLocalMap對象是不同的。


package multiThread;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.concurrent.CyclicBarrier;class MyThread implements Runnable{        private CyclicBarrier cyclicBarrier;        /**     * 第一個線程所持有的ThreadLocalMap對象     */    static Object object1 = null;        /**     * 第二個線程所持有的ThreadLocalMap對象     */    static Object object2 = null;        public MyThread(CyclicBarrier cyclicBarrier)    {        this.cyclicBarrier = cyclicBarrier;    }        @Override    public void run()    {        ThreadLocal threadLocal = new ThreadLocal();                Thread thread = Thread.currentThread();                Class<?> clazz = ThreadLocal.class;                Method createMap = null;                try        {            Method[] methods = clazz.getDeclaredMethods();                        Method createMapMethod = null;                /**             * 通過反射拿到createMap方法的Method對象             */            for(Method method : methods)            {                if("createMap".equals( method.getName() ))                {                    createMapMethod = method;                                    }            }                        System.out.println( createMapMethod );                                    if(createMapMethod != null)            {                createMapMethod.setAccessible( true );                createMapMethod.invoke( threadLocal, thread, "helloworld" );            }                /**             * 通過執行getMap()方法拿到那個LocalThreadMap對象             */            Method getMap = clazz.getDeclaredMethod( "getMap", Thread.class );                        getMap.setAccessible( true );                        System.out.println( getMap.invoke( threadLocal, thread ) );                        if("thread1".equals( Thread.currentThread().getName() ))            {                object1 = getMap.invoke( threadLocal, thread );            }            if("thread2".equals( Thread.currentThread().getName() ))            {                object2 = getMap.invoke( threadLocal, thread );            }                /**             * 等兩個線程都先拿到那個ThreadLocalMap對象才開始執行CyclicBarrier構造方法裡面的那個Runnable介面的匿名類裡的run方法,             * 由最後一個完成的線程執行。             */            cyclicBarrier.await();        }        catch(Exception e)        {            e.printStackTrace();        }                    }}public class ThreadLocalTest{    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InterruptedException, NoSuchMethodException, InstantiationException, InvocationTargetException    {        CyclicBarrier cyclicBarrier = new CyclicBarrier( 2, new Runnable()        {            @Override            public void run()            {                /**                 * 判斷兩個線程對象內所持有的ThreadLocalMap是否為同一對象                 */                System.out.println(MyThread.object1 == MyThread.object2);            }        } );            MyThread myThread = new MyThread( cyclicBarrier );                Thread thread1 = new Thread( myThread, "thread1" );        Thread thread2 = new Thread( myThread, "thread2" );        thread1.start();        thread2.start();            }}



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.