java的ThreadLocal使用實踐之唐僧取經

2021-01-07 軟體開發領路人

大家應該都看過西遊記吧。

西遊記講的是唐僧師徒西天取經,經歷九九八十難,終於完成取經任務,修成正果的故事。

取經時經過了很多的國家。這個過程用java代碼體現會是什麼樣呢。

畫外音:為了截圖不至於太長,注釋使用不太規範

有一個唐僧類。

唐僧類包含了一個取經的方法。取經的方法調用了另外的拜訪各國的方法。最後調用了一個取經完成的方法。

那大家有沒有記得,唐僧沒到一個國家都要找國王在通關文牒上蓋章。這個通過文牒肯定在最後取經完成時也是要展示給唐王驗證的。

那這個通關文牒怎麼體現在上面的代碼中呢。

把通關文牒作為一個方法參數,在所有的方法裡都傳遞一遍?

大家有注意到我代碼裡拜訪各國的方法間的一堆省略號,確定要給這麼多方法都加一個參數,然後每次調用都去傳遞?

其實這些方法的調用都是在一個線程中完成的。對ThreadLocal有一定了解同學,這裡可以使用ThreadLocal了。

下面來看下,用上ThreadLocal後的唐僧取經的代碼。

上面是使用了ThreadLocal的唐僧取經,拜訪各國和取經完成的方法都不需要傳遞參數。只需要在方法中對應的完成對通關文牒的修改以及取經完成時輸出通關文牒即可。

這就是ThreadLocal的一個特點,貫穿整個線程,在線程內傳遞。

細心的朋友可能發現了這個ThreadLocal變量是static的。

那如果有別的唐僧也對這個通關文牒做修改了,那兩個唐僧的通關文牒的內容不就混亂了嗎。

嗯?不是只有一個唐僧嗎。

我們這裡設定的是一個多維空間,存在平行空間的(多線程)。可以同時有多個唐僧進行取經的。

那多個平行空間(多線程)的多個唐僧同時取經,他們的通關文牒會不會搞混亂呢。

可以肯定的告訴大家,不會混亂的。這就是ThreadLocal的另一個特點,變量是線程間隔絕的,每個線程(平行空間)使用的都是自己的一套。

那ThreadLocal是怎麼做到這一點的呢。

讓我們進入ThreadLocal的代碼中看個究竟。

我們從ThreadLocal的get方法進去。

先獲取到當前線程,然後用當前線程獲取到一個ThreadLocalMap(key-value形式),通過當前ThreadLocal對象作為key獲取到的value就是我們存放在ThreadLocal中的通關文牒的內容了。

我們再看看上面代碼中的getMap方法做了什麼。

從getMap方法裡看到方法內部的邏輯是返回了當前線程的一個ThreadLocalMap類型的屬性。從這裡就保證了我們取到的變量是只屬於當前線程的了。

那為什麼從線程取到的這個ThreadLocalMap是一個key-value形式的呢。

想想,唐僧西天取經,不只是通關文牒這個東西一直在用吧(線程中多方法間傳遞使用)。比如紫金缽盂。這樣的話就需要多個ThreadLocal類型的變量了。

這樣就能理解了吧,這個ThreadLocalMap的key就是不同的ThreadLocal變量,而ThreadLocalMap存放的value就是不同的ThreadLocal變量中存放的值了。

今天辛苦唐僧同學了。

有自學java的同學,可以看看這本書

相關焦點

  • ThreadLocal的使用和實現原理
    This class provides thread-local variables.使用其實很簡單,保存值就調用set方法,獲得值調用get方法,最後調用remove方法刪除數據,防止內存洩漏和數據混亂。ThreadLocal的數據結構Thread類中有個變量threadLocals,這個類型為ThreadLocal中的一個內部類ThreadLocalMap,這個類沒有實現map接口,就是一個普通的Java類,但是實現的類似map的功能。
  • Java面試必問,ThreadLocal終極篇
    ThreadLocal<String> localName = new ThreadLocal();localName.set("佔小狼");String name = localName.get();在線程1中初始化了一個ThreadLocal對象localName,並通過set方法,保存了一個值 佔小狼,同時在線程
  • Java 並發編程:深入剖析 ThreadLocal
    =null) connect.close(); }}假設有這樣一個資料庫連結管理類,這段代碼在單線程中使用是沒有任何問題的,但是如果在多線程中使用呢?很顯然,在多線程中使用會存在線程安全問題:第一,這裡面的2個方法都沒有進行同步,很可能在openConnection方法中會多次創建connect;第二,由於connect是共享變量,那麼必然在調用connect的地方需要使用到同步來保障線程安全,因為很可能一個線程在使用connect進行資料庫操作,而另外一個線程調用closeConnection關閉連結。
  • Java Thread 那些事
    :938) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608) at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543) at java.lang.Thread.run
  • 俠說java8-LocalDateTime等時間使用手冊(全),先mark後看
    如何更好的熟悉使用時間api也是學習java8的一個很重要的知識點,下面我們一起來學習學習。本篇文章代碼比較多,可以作為工具,需要使用時,再來查閱。目錄1.普通Date時間如何轉為LocalDateTime?以上是從普通的Date對象轉換成java8時間的操作步驟,需要特別注意下時區的問題。
  • 面試官:知道ThreadLocal嘛?談談你對它的理解?
    在java的多線程模塊中,ThreadLocal是經常被提問到的一個知識點,提問的方式有很多種,可能是循序漸進也可能是就像我的題目那樣,因此只有理解透徹了,不管怎麼問,都能遊刃有餘。二、ThreadLocal怎麼用既然ThreadLocal的作用是每一個線程創建一個副本,我們使用一個例子來驗證一下:從結果我們可以看到,每一個線程都有各自的local值,我們設置了一個休眠時間,就是為了另外一個線程也能夠及時的讀取當前的local值。這就是TheadLocal的基本使用,是不是非常的簡單。
  • java多線程之Thread構造函數(源碼分析)
    官方文檔指出,當java虛擬機中沒有非守護線程了,默認線程也會退出。舉個例子就能明白:守護線程就像飯店裡面的服務員,非守護線程就像是顧客,顧客沒有了,那麼服務員也沒有存在的必要了。2、代碼演示我們通過代碼來演示一下他們的作用,在這裡主要有兩個線程一個是main線程,第二個就是自己創建的thread。
  • 面試:ThreadLocal 為什麼使用神奇的數字 0x61c88647?
    唯一的實例變量threadLocalHashCode是用來進行尋址的hashcode,它由函數nextHashCode()生成,該函數簡單地通過一個增量HASH_INCREMENT來生成hashcode。
  • 一則唐僧取經的寓言故事
    唐僧玄奘前往西天取經時所騎的白馬,只是長安城一家磨坊裡的普通白馬。這匹馬並沒有什麼出眾之處,只不過一生下來就在磨坊裡工作,吃苦耐勞,從不搗亂。    玄奘看中的就是它忠實可靠。待唐僧返回東土大唐,這匹馬也成了取經功臣,被譽為「大唐第一名馬」。    白馬衣錦還鄉,到昔日的磨坊看望老朋友。一大群驢子和老馬圍著白馬,聽白馬講取經途中的見聞以及今日的榮耀,大家稱羨不已。
  • java中ThreadPoolExecutor常識匯總
    這篇文章主要介紹了java中ThreadPoolExecutor常識匯總,線程池技術在並發時經常會使用到,java中的線程池的使用是通過調用ThreadPoolExecutor來實現的。線程池技術在並發時經常會使用到,java中的線程池的使用是通過調用ThreadPoolExecutor來實現的。
  • 使用 ThreadLocal 一次解決老大難問題
    複印後沒有問題,使用ThradLocal相當於複印了教材。1.2 場景2每個線程內需要保存全局變量(例如在攔截器中獲取用戶信息),可以讓不同方法直接使用,避免參數傳遞的麻煩2.對以上場景的實踐2.1 實踐場景1/** * 兩個線程列印日期 */public class ThreadLocalNormalUsage00
  • 西遊記中,唐僧師徒為什麼只能走路去取經?
    西遊記中,唐僧師徒為什麼只能走路去取經?很多人看《西遊記》都有一個很大的疑問:為什麼唐僧師徒要一步步走路到西天去取經?特別是本領高強的孫悟空一個筋鬥雲就搞定了,幹嘛還要那麼折騰人呢?對於這個問題,孫悟空和我們一樣也有過這樣的想法:「這都是我佛如來坐在那極樂之境,沒得事幹,弄了那三藏之經!如若有心勸善,直接送到東土大唐,豈不一樣的萬古流傳?
  • 使用Executors,ThreadPoolExecutor,創建線程池,源碼分析理解
    TestThreadPoolExecutor 示例TestThreadPoolExecutor.javapackage io.ymq.thread.TestThreadPoolExecutor;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.ThreadPoolExecutor
  • 他是鳥修的菩薩,飛的比孫悟空快,給取經造麻煩,唐僧卻感謝萬分
    他是鳥修的菩薩,飛的比孫悟空快,給取經造麻煩,唐僧卻感謝萬分   那麼,取經路上哪一難最特別呢?他是鳥修的菩薩,飛的比孫悟空快,給取經製造麻煩,唐僧卻感謝萬分!   看到這,很多人都會說,飛得比孫悟空快,豈不是金翅大鵬麼?
  • 歪讀西遊記:驚奇發現,取經並非唐僧本願
    如來為拓寬在東土大唐的業務,就安排觀世音菩薩,前去大唐尋找佛教「代理人」,忽悠人去西天天竺國雷音寺取經。然而,筆者在看這段時,驚奇發現,唐僧去西天取經,並非出自他本人意願,而是不得已而為之。具體是怎麼回事兒呢?這得從觀世音菩薩到了東土大唐說起。
  • Java之創建多線程的第一種方式,thread類
    在java.long包下,有這樣一個類java.long.Thread類代表線程,所有的線程對象必須是Thread類或其子類的實例。每一個線程的作用是完成一定的任務,就是執行一段程序流即一段順序執行的代碼。Java中使用線程執行體來代表這段程序流。
  • 普通Java程式設計師學習使用的6個JDK內建工具
    System.out.println("We have accumulated " + map.size() + " entries"); } } ); for(int i = 0; ;i++) { map.put(Integer.toBinaryString(i), i); } }}產生一個 OutOfMemoryError 很簡單(大部分情況下我們無意為之)
  • 面試官:小夥子先來說一下可能引起Java內存洩露的場景吧
    Joshua Bloch曾經評論過線程本地用法:線程池的草率使用與線程局部變量的草率使用可能會導致意外的對象保留,正如在許多地方所指出的那樣。但把責任推到線程本地上是沒有道理的。threadlocal導致內存洩漏一旦保持線程不再活動, threadlocal 就應該被垃圾回收。
  • 孫悟空不懂這幾種語言,怎麼保唐僧到西天取經?唐僧可沒帶翻譯
    孫悟空是中國人非常熟悉的神話人物,唐僧唐三藏到西天取經,全靠他一路降妖除魔,走過千山萬水,歷經九九八十一難,終於到西天取得真經。我們看《西遊記》,看的全是一個熱鬧,沒有認真研究實際問題。事實上,唐僧到西天取經,除了妖魔鬼怪是障礙之外,還有許多障礙,比如語言,就是取經途中的最大障礙。《西遊記》裡的唐僧到西天取經,並沒有帶翻譯,這一路上他如何交流通交?從歷史上唐三藏取經的路線看,他要經過新疆、吉爾吉斯斯坦、阿富汗、巴基斯坦,最經到達印度。
  • 在《西遊記》中,看唐僧取經路上的「豔遇」小故事(中篇)
    在《西遊記》中,看唐僧取經路上的「豔遇」小故事之女兒國國王文/簾外讀史聲原創,未經許可禁止轉載今天接著講西遊記我們的御弟哥哥豔遇小故事。師徒四人帶著疲倦的身體再次踏上取經之路,等待他們下一次的劫難。話說他們走著走著就來到女兒國,這一站專門為唐僧設置的豔遇站。他們到了女兒國引起全國上下的沸騰,在那個很少見男人的國度,竟然有幾個不知天高地厚的傢伙闖進來,真是讓女兒國這些臣民為他們的勇氣點讚?為什麼這麼說?