一句話本質
為每個線程創建獨立的變量副本,實現多線程環境下數據的安全隔離(線程操作自己的副本,互不影響)。
關鍵解讀:
-
核心機制
? 同一個ThreadLocal
對象(如示意圖中的紅色區域tl
)被多個線程共享。? 每個線程調用
set()
/get()
時,實際訪問的是自己線程的專屬存儲空間(如圖中的藍色和綠色區域)。? 例如:線程1設置
"蕭炎"
,線程2設置"藥塵"
,但各自get()
時互不干擾。 -
線程安全的根源
? 數據不共享:每個線程的變量副本獨立存儲(如ThreadLocal
內部通過ThreadLocalMap
實現線程隔離)。? 無需加鎖:天然規避多線程競爭,性能更高。
-
典型應用場景
? 數據庫連接(每個線程獨立Connection
)? 用戶會話信息透傳(如身份信息跨方法傳遞)
? 非線程安全工具類(如
SimpleDateFormat
的線程隔離使用)
圖片中的直接印證:
? 兩個線程操作同一個 tl
(紅色區域),但分別 set("蕭炎")
和 set("藥塵")
。
? 多次 tl.get()
始終返回自己線程設置的值,直觀體現了“變量副本隔離”的特性。
總結:
ThreadLocal = 線程專屬儲物柜
? 全局只有一個柜子管理員(ThreadLocal
對象)
? 但每個線程(人)有自己的獨立儲物格(變量副本)
? 存/取數據時,自動匹配當前線程的儲物格,絕對安全,永不串用。
所以我們對代碼進行修改
創建一個工具類ThreadLocalUtil
代碼如下:
package com.itheima.utils;import java.util.HashMap;
import java.util.Map;/*** ThreadLocal 工具類*/
@SuppressWarnings("all")
public class ThreadLocalUtil {//提供ThreadLocal對象,private static final ThreadLocal THREAD_LOCAL = new ThreadLocal();//根據鍵獲取值public static <T> T get(){return (T) THREAD_LOCAL.get();}//存儲鍵值對public static void set(Object value){THREAD_LOCAL.set(value);}//清除ThreadLocal 防止內存泄漏public static void remove(){THREAD_LOCAL.remove();}
}
在攔截器中修改代碼增加把業務數據存儲到threadLocal中
然后在usercontroller中對代碼進行修改,重新獲取username對象
最后不要忘記在攔截器調用remove進行釋放