1. 程式人生 > >ThreadLocal執行緒本地變數的超詳細解析

ThreadLocal執行緒本地變數的超詳細解析

              前段時間面試都遇到了有關ThreadLocal有關的問題,今天正好寫到了多執行緒,乾脆對ThreadLocal進行一個從簡單理解,到使用,到原始碼理解的學習和分析。

              1.ThreadLocal是什麼

              ThreadLocal正如他的中文翻譯 執行緒本地變數所說,顧名思義,就是每個執行緒自己的本地變數。簡單的來說,就是在多執行緒的程式中,我們一般會申請共享變數。給所有執行緒使用。但是很多情況下,每個執行緒會對共享變數進行改變。比如,一個String 型別的static變數,執行緒一將String 賦值為 “執行緒一

,然後在跑其他的邏輯的時候,第二個執行緒將String 又改成了執行緒二”,那麼就會出個問題,執行緒一跑到後面在對該String進行使用的時候,就發現值已經被改變了。

                       ThreadLocal的價值就體現了出來。就是在每個執行緒裡面對變數單獨記錄儲存。這樣,執行緒二對String的改變就是對自己內部改變,不會影響別的執行緒中的String值。

              針對這個,寫個程式碼進行了一個測試,方便理解。

package zxy.maven.product;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

//
public class ThreadTest {
	// threadLocal Test
	public static ThreadLocal<String> threadLocal = new ThreadLocal<String>();
    
	public static String baseString ="";
	
	
	public static ExecutorService  executorService=Executors.newFixedThreadPool(4);

	
	private static void setTLocal(String value) {
		threadLocal.set(value);
	}

	private static String getTlocal() {
		return "ThreadLocal儲存:"+Thread.currentThread().getName()+" : "+ threadLocal.get();
	}
	
	private static void setBLocal(String value) {
		baseString=value;
	}

	private static String getBlocal() {
		return "Baseocal儲存:   "+Thread.currentThread().getName()+" : "+baseString;
	}
	
	
	
	public static void main(String[] args) throws InterruptedException {

		Thread thread=new Thread(new Runnable() {
			public void run() {
				setTLocal("子執行緒一儲存變數");
				try {
					//睡眠一秒,模擬在處理某些程式
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(getTlocal());
			}
		});
		
		Thread thread2=new Thread(new Runnable() {
			public void run() {
				setTLocal("子執行緒二儲存變數");
				System.out.println(getTlocal());
			}
		});
		
		executorService.execute(thread);
		executorService.execute(thread2);
		
		setTLocal("主執行緒儲存變數");
		System.out.println(getTlocal());
		
		Thread.sleep(1000);
		
		
		
		Thread thread3=new Thread(new Runnable() {
			public void run() {
				setBLocal("子執行緒一儲存變數");
				try {
					//睡眠一秒,模擬在處理某些程式
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.err.println(getBlocal());
			}
		});
		
		Thread thread4=new Thread(new Runnable() {
			public void run() {
				setBLocal("子執行緒二儲存變數");
				System.err.println(getBlocal());
			}
		});
		
		executorService.execute(thread3);
		executorService.execute(thread4);
		
		setBLocal("主執行緒儲存變數");
		System.err.println(getBlocal());	
	}	
}

           

                     看到結果,ThreadLocal儲存的變數沒有因為其他原因改變。但是Basecal的變了,因為當執行的時候,主執行緒執行完了輸出,執行緒一將String 修改為“子執行緒一儲存變數,進入睡眠,執行緒二進行修改,改String 為子執行緒二,這時候輸出的時候,就變成了兩個子執行緒二了。

                    如此就體現了ThreadLocal的價值,就是保證執行緒之間的變數處理互不影響。

                   2.ThreadLocal是怎麼實現的執行緒本地

 從程式碼上來看看怎麼實現了這個功能吧。
                    ThreadLocal內部主要的幾個方法就是   public T get(), public void set(T value), public void remove(),分別是獲取本地變數,儲存本地變數和刪除變數                    從get方法開始看       public T get():
public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
               很簡單,就是先獲取當前正在執行的執行緒,獲取當前執行的執行緒的ThreadLocalMap(每個Thread都有一個名字叫threadLocals  型別為ThreadLocal.ThreadLocalMap的變數)。如果,當前Thread的ThreadLocalMap不為空,即已經通過set或者initialValue初始化過,則直接返回有關物件型別。                如果當前執行緒的ThreadLocalMap為空,則處理setInitialValue方法。
private T setInitialValue() {
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }
                       該方法的作用是對ThreadLocalMap進行初始化。首先如果有重寫initialValue方法,則將重寫的初始化物件給T,然後在嘗試查一下當前執行緒ThreadLocalMap有沒有值,有值則將初始化的值也set進去,沒有值得話就建立一個新的map,把當前執行緒和T當做引數傳遞給createMap。
  void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
            createMap很簡單,就是把當前執行緒的ThreadLocalMap用初始化的值儲存一下。               public void set(T value)
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
         看完了setInitialValue方法,其實這個就太簡單了,只是把初始化的那個值換成了set 的value值,儲存在了ThreadLocalMap裡面,其他沒有變化。     public void remove()
     public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }
                   remove方法也非常簡單,就是獲取當前執行緒的ThreadLocalMap,如果不為空的話,把他清除掉。

                 看完了這些方法,基本上ThreadLocal也就完全明白了,其實還是比較簡單的一個實現的東西。

相關推薦

ThreadLocal執行本地變數詳細解析

              前段時間面試都遇到了有關ThreadLocal有關的問題,今天正好寫到了多執行緒,乾脆對ThreadLocal進行一個從簡單理解,到使用,到原始碼理解的學習和分析。               1.ThreadLocal是什麼          

執行本地變數ThreadLocal

文章目錄 一、什麼是ThreadLocal 二、原始碼實現 set方法實現 get方法實現 remove方法實現 三、記憶體洩漏問題 一、什麼是ThreadLoca

執行本地變數 - ThreadLocal

參考網址: https://www.jianshu.com/p/98b68c97df9b (此處連結不知為何,點選後跳轉頁面還是本頁,建議複製開啟) 1、ThreadLocal是什麼? 執行緒本地變數,其為每個使用該變數的執行緒提供獨立的變數副本,所以每個執行緒都可以獨立的改變自己

深入理解java:執行本地變數 java.lang.ThreadLocal

ThreadLocal,很多人都叫它做執行緒本地變數,也有些地方叫做執行緒本地儲存,其實意思差不多。 可能很多朋友都知道ThreadLocal為變數在每個執行緒中都建立了一個副本,那樣每個執行緒可以訪問自己內部的副本變數。 這句話從表面上看起來理解正確,但實際上這種理解是不太正確的。下面我們

Java併發(二十):執行本地變數ThreadLocal

ThreadLocal是一個本地執行緒副本變數工具類。 主要用於將私有執行緒和該執行緒存放的副本物件做一個對映,各個執行緒之間的變數互不干擾,在高併發場景下,可以實現無狀態的呼叫,特別適用於各個執行緒依賴不同的變數值完成操作的場景。 一、ThreadLocal的核心機制 每個Thread執行緒內部都有一個Ma

JAVA多執行wait與notify詳細解析(由生產者和消費者案例引出)

生產者和消費者這個關係是個經典的多執行緒案例。現在我們編寫一個Demo來模擬生產者和消費者之間的關係。 假如有兩個類,一個是資料生產者類DataProvider,另一個是資料消費者類DataConsumer,這兩個類同時對資料類Data進行操作,生產者類負責生產資料,消費者類負責消費資料,下面是

ThreadLocal執行變數

一、ThreadLocal本地執行緒變數     一般的Web應用劃分為展現層、服務層和持久層三個層次,在不同的層中編寫對應的邏輯,下層通過介面向上層開放功能呼叫。在一般情況下,從接收請求到返回響應所經過的所有程式呼叫都同屬於一個執行緒。    也就是說,同一執行緒貫通N

執行本地變數的理解,將登入資訊存放到執行本地變數

      在獲取使用者的登入資訊時,我們一般從ThreadLocalMap中獲取,ThreadLocalMap中存放的變數就是執行緒本地的變數,是執行緒隔離的,使用執行緒本地變數而非區域性變數的原因:方便我們對這些變數統一管理,免去頻繁地傳參。 ThreadLocal 原

Java多執行學習(詳細總結)

目錄(?)[-]      本文主要講了java中多執行緒的使用方法、執行緒同步、執行緒資料傳遞、執行緒狀態及相應的一些執行緒函式用法、概述等。 首先講一下程序和執行緒的區別:   程序:每個程序都有獨立的程式碼和資料空間(程序上下文),程序間的切換會有較大的

ThreadLocal 執行區域性變數

ThreadLocal 一、概念 ThreadLocal是Thread Local Variable(執行緒區域性變數)的意思。執行緒區域性變數的功能是為每一個使用該變數的執行緒都提供一個變數值的副本,使每一個執行緒都可以獨立的改變自己的副本,而不會和其他執行緒的副本衝突

理解ThreadLocal(執行區域性變數)

ThreadLocal(執行緒區域性變數)概述 ThreadLocal是什麼呢?其實ThreadLocal並非是一個執行緒的本地實現版本,它並不是一個Thread,而是threadlocalvariable(執行緒區域性變數)。也許把它命名為ThreadLocalVa

ThreadLocal 執行範圍內的共享變數

package cn.itcast.heima2; import java.util.HashMap; import java.util.Map; import java.util.Random;    //執行緒範圍內的共享變數 public class ThreadLoc

執行區域性變數的使用ThreadLocal和其底層原理

/*ThreadLocal類:   * 該類提供了執行緒區域性變數,它是一個池 Map<Thread.currentThread,locObj>,  * 池中為每個執行緒儲存一個獨立的區域性變數,  * 每個執行緒可以從這個池中讀取或設定自己的區域性變數。 //

31-執行區域性變數 ThreadLocal

執行緒區域性變數 ThreadLocal 原理,作用 每個Thread維護一個ThreadLocalMap 對映表,使用ThreadLocal物件為弱引用的map集合(即弱引用的物件可以在GC中被回收掉),value為對應的值。其生命週期和執行緒一致。

Java多執行程式設計-(3)-執行本地ThreadLocal的介紹與使用

原文出自 : https://blog.csdn.net/xlgen157387/article/details/78114278 ThreadLocal簡介 我們通過上兩篇的學習,我們已經知道了變數值的共享可以使用public static變數的形式,所有的執行緒都使

執行執行區域性變數ThreadLocal及原理

一、執行緒區域性變數ThreadLocal ThreadLocal為變數在每個執行緒中都建立了一個副本,那麼每個執行緒可以訪問自己內部的副本變數。既然是隻有當前執行緒可以訪問的資料,自然是執行緒安全的。 主要方法: initialValue()方法可以重寫,它預設是返回

ThreadLocal執行範圍內的共享變數

資料庫connection和strut2每個請求用到ThreadLocalimport java.util.Random; public class ThreadLocalTest {     private static ThreadLocal<Integer>

執行學習-執行本地ThreadLocal的介紹與使用

ThreadLocal簡介我們通過上兩篇的學習,我們已經知道了變數值的共享可以使用public static變數的形式,所有的執行緒都使用同一個被public static修飾的變數。那麼如果我們想實現每一個執行緒都有自己的共享變數該如何解決哪?JDK提供的ThreadLoc

Java中執行區域性變數ThreadLocal使用教程及原始碼分析

       在Java多執行緒程式設計中有時候會遇見執行緒本地區域性變數ThreadLocal這個類,下面就來講講ThreadLocal的使用及原始碼分析。        ThreadLocal 是Thread Local Varial(執行緒區域性變數)的意思,每個執行

執行區域性變數ThreadLocal的簡單使用

今天來說說ThreadLocal的使用: 什麼是ThreadLocal:ThreadLocal是執行緒區域性變數,所謂的執行緒區域性變數,就是僅僅只能被本執行緒訪問,不能線上程之間進行共享訪問的變數。在各個Java web的各種框架中ThreadLocal幾乎已經被用