日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ThreadLocal初识

發布時間:2025/3/12 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ThreadLocal初识 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 背景
  • ThreadLocal的作用
  • ThreadLocal特性
  • ThreadLocal實現
    • 1. T get()
    • 2. set(T value)
    • 3. remove()
  • 驗證
    • 一個對象只存一個數據
    • 多少個對象就能存多少個數據


背景

這兩天稍微有點空,在追溯之前的android 7.0之前的手機用View.post 出現不執行的問題時,結識了ThreadLocal,且問題的原因也是系統內部使用ThreadLocal造成的。因此記錄并分享之。
關于view.post不執行的坑點

ThreadLocal的作用

ThreadLocal的作用主要是做數據隔離,填充的數據(對象)只屬于當前線程,變量的數據對別的線程而言是相對隔離的,在多線程環境下,一個線程防止自己的變量被其它線程篡改。1
A線程存了一個對象objectA,此時B線程通過同一個ThreadLocal對象去取的話是取不到objectA的。

通俗的講:
A、B錢包都沒錢了,A從銀行取了1000 人民幣,裝入了自己的錢包,B去商店買1000的商品,此時B從自己錢包里面拿錢時,錢包是空的。
AB好比是線程,存的數據就是1000人民幣,消費的時候只能從自己錢包拿出來,只是A和B存到錢包的過程可以通過ThreadLocal來完成的。

ThreadLocal特性

ThreadLocal和Synchronized都是為了解決多線程中相同變量的訪問沖突問題,不同的點是2

  • Synchronized是通過線程等待,犧牲時間來解決訪問沖突
  • ThreadLocal是通過每個線程單獨一份存儲空間,犧牲空間來解決沖突,并且相比于Synchronized,ThreadLocal具有線程隔離的效果,只有在線程內才能獲取到對應的值,線程外則不能訪問到想要的值。
  • ThreadLocal實現

    ThreadLocal 對外一共提供了get、set和remove的函數,這里請注意set和get不是一般bean的get和set。而且巧妙的使用了調用棧關系,并取了當前調用的線程來做一些列的處理,所以與線程密切相關。調用線程指的是執行get、set、和remove的線程。

    1. T get()

    public T get() {// Optimized for the fast path.Thread currentThread = Thread.currentThread();Values values = values(currentThread);if (values != null) {Object[] table = values.table;int index = hash & values.mask;if (this.reference == table[index]) {return (T) table[index + 1];}} else {values = initializeValues(currentThread);}return (T) values.getAfterMiss(this);}

    2. set(T value)

    /*** Sets the value of this variable for the current thread. If set to* {@code null}, the value will be set to null and the underlying entry will* still be present.** @param value the new value of the variable for the caller thread.*/public void set(T value) {Thread currentThread = Thread.currentThread();Values values = values(currentThread);if (values == null) {values = initializeValues(currentThread);}values.put(this, value);}

    3. remove()

    /*** Removes the entry for this variable in the current thread. If this call* is followed by a {@link #get()} before a {@link #set},* {@code #get()} will call {@link #initialValue()} and create a new* entry with the resulting value.** @since 1.5*/ public void remove() {Thread currentThread = Thread.currentThread();Values values = values(currentThread);if (values != null) {values.remove(this);}} Values values(Thread current) {return current.localValues; }

    從get/set/remove實現中能看出,都是取當前線程,再從當前線程中拿出values,從values取出或put。而這個values是屬于Thread的莫不是ThreadLocal的,這點要注意一下。value內部包含了數組,那么程序存取的數據對象就是放到這個數組中的,并且是以hash進行映射,和HashMap的實現不一樣,思想幾乎一樣。

    驗證

    接下來需要代碼實際演示一下,不然死不了心。那么問題來了,從get和set來看都只有一個value參數,假如要set多個怎么辦,而且set又是以ThreadLocal對象作為key去“存儲”的。不要慌,既然是以ThreadLocal對象作為key,那就多創建幾個ThreadLocal對象,多個對象被一個線程調用,那么多個數據就被存到了同一個線程的存儲區(table)中。

    一個對象只存一個數據

    static void testThreadLoacal() {final ThreadLocal<String> threadLocal = new ThreadLocal<>();String str = "Test ThreadLocal";threadLocal.set(str);System.out.println("main thread set value:" + str);new Thread() {@Overridepublic void run() {String str = threadLocal.get();System.out.println("sub thread get value:" + str);}}.start();str = threadLocal.get();System.out.println("main thread get value:" + str);}

    輸出結果:

    main thread set value:Test ThreadLocal
    main thread get value:Test ThreadLocal
    sub thread get value:null

    一個線程set的值,其他線程取不到,只有相同線程才能取到。多個線程同時用一個ThreadLocal對象,其數據是還是屬于各自線程。

    多少個對象就能存多少個數據

    由于是泛型,所以多個ThreadLocal不但可以存多個同類型的對象,甚至可以存多個不同類型的 對象。

    static void testThreadLoacals() {final ThreadLocal<String> threadLocal = new ThreadLocal<>();final ThreadLocal<A> threadLocal1 = new ThreadLocal<>();String str = "main Thread";threadLocal.set(str);System.out.println("threadLocal main thread set str value:" + str);A a = new A();threadLocal1.set(a);System.out.println("threadLocal1 main thread set A class value:" + a);new Thread() {@Overridepublic void run() {String str = threadLocal.get();System.out.println("sub thread get value:" + str);str = "sub thread";threadLocal.set(str);System.out.println("sub thread set value:" + str);System.out.println("sub thread set value:" + threadLocal.get());}}.start();str = threadLocal.get();System.out.println("main thread 1 get value:" + str);System.out.println("main thread 1 get A class value:" + threadLocal1.get());try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}System.out.println("main thread 2 get value:" + threadLocal.get());}

    threadLocal set 一個String
    threadLocal1 set的是A類的對象

    輸出結果:

    threadLocal main thread set str value:main Thread
    threadLocal1 main thread set A class value:com.eagle.app.MainJava$A@12a3a380
    main thread 1 get value:main Thread
    main thread 1 get A class value:com.eagle.app.MainJava$A@12a3a380
    sub thread get value:null
    sub thread set value:sub thread
    sub thread set value:sub thread
    main thread 2 get value:main Thread

    多個線程同時用多個ThreadLocal對象,其數據是還是屬于各自線程。


  • Java中ThreadLocal的實際用途是啥 ??

  • ingxin ThreadLocal ??

  • 總結

    以上是生活随笔為你收集整理的ThreadLocal初识的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。