首頁  >  文章  >  Java  >  ThreadLocal解決多線程程式的實例

ThreadLocal解決多線程程式的實例

零下一度
零下一度原創
2017-07-26 16:52:431952瀏覽

       相信讀者在網路上也看了很多關於ThreadLocal的資料,許多部落格都這樣說:ThreadLocal為解決多執行緒程式的同時問題提供了一種新的思路;ThreadLocal的目的是為了解決多執行緒存取資源時的共享問題。如果你也這麼認為的,那現在給你10秒鐘,清空之前對ThreadLocal的錯誤的認知!
看看JDK中的原始碼是怎麼寫的:

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類別用來提供線程內部的局部變數。這種變數在多執行緒環境下存取(透過get或set方法存取)時能保證各個執行緒裡的變數相對獨立於其他執行緒內的變數。 ThreadLocal實例通常來說都是private static類型的,用於關聯線程和線程的上下文。

可以總結為一句話:ThreadLocal的作用是提供線程內的局部變量,這種變量在線程的生命週期內起作用,減少同一個線程內多個函數或組件之間一些公共變量的傳遞的複雜度。
舉個例子,我出門需要先搭公車再做地鐵,這裡的搭公車和搭地鐵就好比是同一個線程內的兩個函數,我就是一個線程,我要完成這兩個函數都需要同一個東西:公車卡(北京公車和地鐵都使用公車卡),那麼我為了不向這兩個函數都傳遞公車卡這個變數(相當於不是一直帶著公車卡上路),我可以這麼做:將公車卡事先交給一個機構,當我需要刷卡的時候再向這個機構要公車卡(當然每次拿的都是同一張公車卡)。這樣就能達到只要是我(同一個線程)需要公車卡,何時何地都能向這個機構要的目的。

有人要說了:你可以將公車卡設定為全域變數啊,這樣不是也能何時何地都能取公車卡嗎?但是如果有很多個人(很多個線程)呢?大家可不能都使用同一張公車卡吧(我們假設公車卡是實名認證的),這樣不就亂套了嘛。現在明白了吧?這就是ThreadLocal設計的初衷:提供線程內部的局部變量,在本線程內隨時隨地可取,並隔離其他線程。

(1)ThreadContext8742468051c85b06f0a0af9e3e506b5c為基於鍵/值對的當前執行緒提供了一種綁定和非綁定物件的方法。

這個類別提供線程局部變數。 這些變數與普通的變數不同,因為每個存取一個執行緒的執行緒(透過其get或set方法)都有自己的獨立初始化變數的副本。

ThreadLocal實例通常是希望將狀態與執行緒關聯的類別中的私人靜態欄位(例如:一個使用者ID或交易ID )。 每個執行緒都對執行緒本地變數的副本有一個隱含引用,

#只要執行緒還活著,ThreadLocal實例就可以存取;在一個執行緒消失之後,所有執行緒本地實例的副本都將被垃圾收集(除非存在其他引用)。

8742468051c85b06f0a0af9e3e506b5c為執行緒中儲存的物件。即一個類別T是線程的一個類別屬性。

常用的方法有:

 1 public class ThreadLocal8742468051c85b06f0a0af9e3e506b5c { 2  3 //设置属性 4  5 public void set(T value) { 6 Thread t = Thread.currentThread(); 7 ThreadLocalMap map = getMap(t); 8 if (map != null) 9 map.set(this, value);10 else11 createMap(t, value);12 }13 14 //获取属性15 16 public T get() {17 Thread t = Thread.currentThread();18 ThreadLocalMap map = getMap(t);19 if (map != null) {20 ThreadLocalMap.Entry e = map.getEntry(this);21 if (e != null)22 return (T)e.value;23 }24 return setInitialValue();25 }26 27 //获取线程的 ThreadLocal.ThreadLocalMap28 29 ThreadLocalMap getMap(Thread t) {30 return t.threadLocals;31 }32 33 }34 35 //新建一个线程本地的localMap36 37 void createMap(Thread t, T firstValue) {38 t.threadLocals = new ThreadLocalMap(this, firstValue);39 }

(2)使用範例:連線、會話如下:

 1 private static ThreadLocal2918aec6680a0636f336c3e736b1ff5a connectionHolder 2 = new ThreadLocal2918aec6680a0636f336c3e736b1ff5a() { 3 public Connection initialValue() { 4     return DriverManager.getConnection(DB_URL); 5 } 6 }; 7   8 public static Connection getConnection() { 9 return connectionHolder.get();10 }
 1 private static final ThreadLocal threadSession = new ThreadLocal(); 2   3 public static Session getSession() throws InfrastructureException { 4     Session s = (Session) threadSession.get(); 5     try { 6         if (s == null) { 7             s = getSessionFactory().openSession(); 8             threadSession.set(s); 9         }10     } catch (HibernateException ex) {11         throw new InfrastructureException(ex);12     }13     return s;14 }

 

以上是ThreadLocal解決多線程程式的實例的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn