最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java線程變量ThreadLocal詳細解讀

 更新時間:2024年01月18日 09:31:56   作者:小白不很白  
這篇文章主要介紹了Java線程變量ThreadLocal詳細解讀,多線程訪問同一個變量的時候,很容易出現(xiàn)問題,特別是多線程對一個共享變量進行寫入的時候,為了線程的安全在進行數(shù)據(jù)寫入時候會進行數(shù)據(jù)的同步,需要的朋友可以參考下

Java線程變量ThreadLocal

多線程訪問同一個變量的時候,很容易出現(xiàn)問題,特別是多線程對一個共享變量進行寫入的時候。為了線程的安全在進行數(shù)據(jù)寫入時候會進行數(shù)據(jù)的同步。

在這里插入圖片描述

如上圖: 如果要想實現(xiàn)多個線程操作同一個數(shù)據(jù)而不被其他線程所影響,就必須加鎖操作,加鎖又增加了使用的復雜度。

ThredLocal的用處就是當多個線程操作同一個變量的時候可以在創(chuàng)建一個ThredLocal,把共享變量復制到線程的本地threadLocals(threadLocals是Thread的成員變量) 中,這樣各個線程進行操作的時候只能操作自己本地數(shù)據(jù),這樣就不會存儲在線程不安全的問題了。

下面舉個例子:

public class ThreadLocalTest {
    // 創(chuàng)建一個ThreadLocal
    static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
    static Integer num = 5;
        public static void main(String[] args) throws InterruptedException {
                new Thread(()->{
                    // 線程1 把num 同步到threadLocal中
                    threadLocal.set(num);
                    // 線程1 獲取threadLocal中的數(shù)據(jù)
                    System.out.println("線程1: " + threadLocal.get());
                }).start();
                new Thread(()->{
                    // 線程2 獲取threadLocal中的數(shù)據(jù)
                    System.out.println("線程2: "+ threadLocal.get());
                }).start();
            System.out.println("主線程: " + threadLocal.get());
        }
}

結果:由上面的返回可以知道,當在線程1設置了設置了數(shù)據(jù)時在線程2是訪問不到的**,主線程**也訪問不到。

ThreadLocal的實現(xiàn)原理

由下圖可知 Thread類中有一個成員變量 ThreadLocal.ThreadLocalMap **threadLocals **= **null ** 是ThreadLocalMap類型的,本地變量都是存儲在ThreadLocalMap中的,ThreadLocal只是一個外殼。ThreadLocalMap是ThreadLocal中的內部類,是一個定制化的Map形式,那就代表一個線程可以有多個ThreadLocal本地變量。key就是ThreadLocal本身,value就是存儲的本地變量。

在這里插入圖片描述

1.set()

 public void set(T value) {
      // 獲取當前線程
      Thread t = Thread.currentThread();
     // 獲取線程的成員變量threadLocals
      ThreadLocalMap map = getMap(t);
      if (map != null)
          // ThreadLoacl 對象為key  同步的變量為value
          map.set(this, value);
      else
          // 如果是第一次 則創(chuàng)建ThreadLocalMap 并且賦值
            createMap(t, value);
  }
// 獲取線程的成員變量threadLocals
ThreadLocalMap getMap(Thread t) {
     return t.threadLocals;
}
// 第一次創(chuàng)建ThreadLocalMap(this, firstValue)
void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
}

2.get()

public T get() {
    // 獲取當前線程
    Thread t = Thread.currentThread();
    // 獲取線程的成員變量threadLocals
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        // 獲取hashMap的值
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    // 如果為null
    return setInitialValue();
}
 private T setInitialValue() {
  // 初始化值為null
  T value = initialValue();
     // 獲取當前線程
  Thread t = Thread.currentThread();
   // 獲取當前線程的threadLocals 成員變量
  ThreadLocalMap map = getMap(t);
   // 如果數(shù)據(jù)為null則會存儲把這個ThreadLocal的對象在這個線程的值存儲為null
  if (map != null)
      map.set(this, value);
  else
      createMap(t, value);
  return value;
}
//初始化值
protected T initialValue() {
    return null;
}

3. remove()

public void remove() {
    ThreadLocalMap m = getMap(Thread.currentThread());
    if (m != null)
        m.remove(this);
}

ThreadLocal不具備繼承性

從上面的set接口 和 get接口就不難看出我們現(xiàn)在存儲、獲取、刪除數(shù)據(jù)都是在當前線程threadLocals成員變量中存儲的。所以父線程和存儲的數(shù)據(jù)在子線程中獲取不了,在子線程中存儲的數(shù)據(jù)在父線程中存儲不了。

例:

public class ThreadLocalTest {
    static ThreadLocal<Integer> stringThreadLocal = new ThreadLocal<>();
    static Integer num = 5;
        public static void main(String[] args) throws InterruptedException {
                new Thread(()->{
                    stringThreadLocal.set(num);
                    System.out.println("線程1: " + stringThreadLocal.get());
                    new Thread(()->{
                        System.out.println("線程1的子線程: " + stringThreadLocal.get());
                    }).start();
                }).start();
        }
}

結果:

在這里插入圖片描述

InheritableThreadLocal類

為了解決上述問題,為了讓子類能夠訪問父類的數(shù)據(jù),則InheritableThreadLocal應用而生。

首先InheritableThreadLocal類繼承了ThreadLocal類 并重寫了ThreadLocla的三個方法

public class InheritableThreadLocal<T> extends ThreadLocal<T> {
    // 只返回父類線程的值
    protected T childValue(T parentValue) {
        return parentValue;
    }
    // 獲取線程inheritableThreadLocals值
    ThreadLocalMap getMap(Thread t) {
       return t.inheritableThreadLocals;
    }
    // 創(chuàng)建當前線程的inheritableThreadLocals
    void createMap(Thread t, T firstValue) {
        t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
    }
}

再看下Thread創(chuàng)建的init方法

  private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
     ......
       // 獲取父類線程
        Thread parent = currentThread();
     ........
       // 如果 在創(chuàng)建子類線程的時候如果返現(xiàn)父類線程的數(shù)據(jù)不為null 則把父類線程的數(shù)據(jù)存儲到子類線程的
         //inheritableThreadLocals成員變量中去
        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
    }

這樣父類線程的inheritThreadLocals數(shù)據(jù)就存儲到了子類變量中去了。 值得注意的事,雖然能用父類的放進去的值,但是不影響父類的操作,也就是子類和父類的值是隔離開的。

package com.example.spring;


public class ThreadLocalTest {

    static ThreadLocal<Integer> stringThreadLocal = new ThreadLocal<>();
    static InheritableThreadLocal<Integer> integerInheritableThreadLocal = new InheritableThreadLocal();

    static Integer num = 5;

        public static void main(String[] args) throws InterruptedException {

                new Thread(()->{
                    integerInheritableThreadLocal.set(num);
                    System.out.println("線程1: " + integerInheritableThreadLocal.get());
                    new Thread(()->{
                        integerInheritableThreadLocal.set(4);
                        System.out.println("線程1的子線程: " + integerInheritableThreadLocal.get());
                    }).start();
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("線程1的最終結果:" + integerInheritableThreadLocal.get());
                }).start();
        }
}

在這里插入圖片描述

到此這篇關于Java線程變量ThreadLocal詳細解讀的文章就介紹到這了,更多相關Java線程變量ThreadLocal內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Spring Boot項目使用Flyway的詳細教程

    Spring Boot項目使用Flyway的詳細教程

    這篇文章主要介紹了Spring Boot項目使用Flyway,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • log4j2日志異步打印(實例講解)

    log4j2日志異步打印(實例講解)

    下面小編就為大家?guī)硪黄猯og4j2日志異步打印(實例講解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • Java實現(xiàn)ATM系統(tǒng)超全面步驟解讀建議收藏

    Java實現(xiàn)ATM系統(tǒng)超全面步驟解讀建議收藏

    這篇文章主要為大家詳細介紹了用Java實現(xiàn)簡單ATM機功能,文中實現(xiàn)流程寫的非常清晰全面,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • mybatis-plus實現(xiàn)邏輯刪除的示例代碼

    mybatis-plus實現(xiàn)邏輯刪除的示例代碼

    在大多數(shù)公司里,都會采用邏輯刪除的方式,本文主要介紹了mybatis-plus實現(xiàn)邏輯刪除的示例代碼,具有一定的參考價值,感興趣的可以了解一下
    2024-05-05
  • BufferedWriter如何使用write方法實現(xiàn)換行

    BufferedWriter如何使用write方法實現(xiàn)換行

    這篇文章主要介紹了BufferedWriter如何使用write方法實現(xiàn)換行的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java?GUI實現(xiàn)學生成績管理系統(tǒng)

    Java?GUI實現(xiàn)學生成績管理系統(tǒng)

    這篇文章主要為大家詳細介紹了Java?GUI實現(xiàn)學生成績管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • java 中sleep() 和 wait() 的對比

    java 中sleep() 和 wait() 的對比

    這篇文章主要介紹了java 中sleep() 和 wait() 的對比的相關資料,需要的朋友可以參考下
    2017-04-04
  • 基于java file 文件操作operate file of java的應用

    基于java file 文件操作operate file of java的應用

    本篇文章介紹了,基于java file 文件操作operate file of java的應用。需要的朋友參考下
    2013-05-05
  • 使用Flyway進行Java數(shù)據(jù)庫版本控制的操作指南

    使用Flyway進行Java數(shù)據(jù)庫版本控制的操作指南

    今天我們將深入探討如何使用Flyway進行Java數(shù)據(jù)庫版本控制,Flyway是一個流行的數(shù)據(jù)庫遷移工具,用于管理和自動化數(shù)據(jù)庫模式的演變,文中通過代碼示例介紹的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2024-07-07
  • 詳解基于JWT的springboot權限驗證技術實現(xiàn)

    詳解基于JWT的springboot權限驗證技術實現(xiàn)

    這篇文章主要介紹了詳解基于JWT的springboot權限驗證技術實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-11-11

最新評論

泗洪县| 响水县| 三门县| 绥中县| 福清市| 海城市| 宁都县| 乐清市| 嵊泗县| 法库县| 共和县| 昂仁县| 平江县| 余干县| 庆云县| 名山县| 福鼎市| 景东| 仪征市| 扎鲁特旗| 屏南县| 武功县| 古蔺县| 望谟县| 乐至县| 南京市| 富蕴县| 梁平县| 临泉县| 河西区| 光山县| 昭通市| 新河县| 栾川县| 南川市| 图片| 兴山县| 红桥区| 武冈市| 六盘水市| 怀安县|