实现threadlocal_ThreadLocal如何实现?
實現threadlocal
這是我上周的帖子的后續文章,其中我解釋了ThreadLocal用法背后的動機 。 從帖子中我們可以回憶起,如果您希望為每個線程擁有一個獨立初始化的變量副本,則ThreadLocal確實是一個很酷的概念。 現在,好奇的人可能已經開始問“我如何在Java中實現這樣的概念”?
否則,您可能會覺得這不是一個有趣的話題–畢竟,您在這里所需的只是一張地圖 ,不是嗎? 在處理ThreadLocal <T>時 ,將解決方案實現為HashMap <Thread,T>并以Thread.currentThread()為鍵似乎是明智的選擇。 其實不是那么簡單。 因此,如果您有五分鐘的時間,請忍受我,我將指導您完成一個漂亮的設計概念。
簡單的HashMap解決方案的第一個明顯問題是線程安全性。 由于HashMap并不是為支持并發使用而構建的,因此我們無法在多線程環境中安全地使用該實現。 幸運的是,我們不需要花很多時間來解決問題-ConcurrentHashMap <Thread,T>看起來像是天作之合。 檢索的完全并發性和可調整的預期更新并發性正是我們首先需要的。
現在,如果您將基于ConcurrentHashMap的解決方案應用于JDK源代碼中的ThreadLocal實現,則會帶來兩個嚴重的問題。
- 首先,在Map結構中將線程作為鍵。 由于該映射永遠不會被垃圾回收,因此最終您將永遠保持對該線程的引用,從而阻止該線程成為GCd。 不情愿的是,您在設計中造成了巨大的內存泄漏。
- 第二個問題可能需要更長的時間才能浮出水面,但是即使在幕后進行了巧妙的分段以減少鎖爭用的機會, ConcurrentHashMap仍然承擔同步開銷。 在同步需求仍然存在的情況下,您仍然擁有一個結構,可能成為瓶頸的根源。
但是,讓我們首先開始解決最大的問題。 如果我們的引用是指向相關線程的最后一個引用,則我們的數據結構需要允許對線程進行垃圾回收。 再次,第一個可能的解決方案是盯著我們看-為什么不使用WeakReferences代替我們通常對對象的引用 ? 因此,實現現在看起來類似于以下內容:
Collections.synchronizedMap(new WeakHashMap<Thread, T>())現在,我們已經解決了泄漏問題–如果除我們之外沒有人引用Thread ,則可以將其定型并進行垃圾回收。 但是我們仍然沒有解決并發問題。 現在,解決方案實際上是關于跳出思路思考的樣本。 到目前為止,我們已經將ThreadLocal變量視為映射到變量的Threads 。 但是,如果我們顛倒了思路,而是設想了一個解決方案,將ThreadLocal對象映射到每個Thread中的值,該怎么辦? 如果每個線程都存儲該映射,并且ThreadLocal只是該映射的接口,則可以避免同步問題。 更好的是,我們還避免了GC帶來的問題!
確實,當我們打開ThreadLocal和Thread類的源代碼時 ,我們看到這正是在JDK中實際實現該解決方案的方式:
public class Thread implements Runnable {ThreadLocal.ThreadLocalMap threadLocals = null;// cut for brevity }public class ThreadLocal<T> {static class ThreadLocalMap {// cut for brevity}ThreadLocalMap getMap(Thread t) {return t.threadLocals;}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();}private T setInitialValue() {T value = initialValue();Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);return value;}// cut for brevity }所以我們在這里。 Thread類保留對ThreadLocal.ThreadLocalMap實例的引用,該實例是使用對鍵的弱引用構建的。 以相反的方式構建結構,由于ThreadLocal只能訪問當前線程中的值,因此完全避免了線程爭用問題。 另外,當Thread完成工作時,映射可以進行垃圾回收,因此我們還避免了內存泄漏問題。
 希望您對設計有所了解,因為它確實是解決復雜問題的理想解決方案。 我確實認為閱讀源代碼是學習新概念的理想方式。 而且,如果您是Java開發人員,那么,比閱讀Joshua Bloch和Doug Lea集成到JDK的源代碼更好的地方是獲得知識的地方? 
翻譯自: https://www.javacodegeeks.com/2013/11/how-is-threadlocal-implemented.html
實現threadlocal
總結
以上是生活随笔為你收集整理的实现threadlocal_ThreadLocal如何实现?的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 8.4版本文森特最新符文(文森特符文出装
- 下一篇: 带有Spring Boot 2.0的Sp
