歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Java中的ThreadLocal

用法

多個線程在調用同一個方法的時候,會有並發問題,解決這種問題最簡單的辦法就是將數據保存在Thread的自己的結構中,也就是ThreadLocal的作用了。用法如下:

classJavaBean{staticThreadLocal<Integer> threadLocal =newThreadLocal<Integer>();publicvoid prepare(){
        threadLocal.set(0);}publicvoid work(){for(int i =0; i <1000; i++){int val = threadLocal.get();
            val++;
            threadLocal.set(val);}System.out.println(threadLocal.get());}}classWorkerextendsThread{JavaBean bean;publicWorker(JavaBean bean){this.bean = bean;}publicvoid run(){
        bean.prepare();
        bean.work();}}publicclassThreadLocalDemo{publicstaticvoid main(String[] args){JavaBean bean =newJavaBean();for(int i =0; i <100; i++){newWorker(bean).start();}}}

從輸出中可以看到,多個線程操作同一個threadLocal時,結果並不會出錯。

可以將ThreadLocal看做是對Thread.threadLocals的封裝,況且在程序中也是不能直接訪問到Thread.threadLocals。

原理

下面簡單看ThreadLocal的原理,在Thread中保存了一個Map,類型可以認為是Map<ThreadLocal, T>,其中T是要保存數據的類型。當要從中取出數據時,調用的流程如下:

Thread.currentThread().threadLocals.getEntry(threadLocal).value

這樣,不同的線程在執行的時候在同一個threadLocal上獲取到的是不同的數據,線程之間的隔離性是通過”各自保存不同的Map”來實現的,而看到的threadLocal對象其實是KEY,在操作前get到的是VALUE。其實自己動手做一個線程安全的數據保存的解決方法也是這個思路。

在ThreadLocalMap中使用的並不是普通的引用保存數據,而是使用WeakReference來做:

staticclassEntryextendsWeakReference<ThreadLocal>{Object value;Entry(ThreadLocal k,Object v){super(k);
        value = v;}}

這樣如果ThreadLocal被釋放了,那麼ThreadLocalMap中的Entry也會被釋放,不至於造成內存洩露。

Copyright © Linux教程網 All Rights Reserved