什么是ThreadLocal
ThreadLocal是java中的線程本地變量,用於每個線程保存自己的變量,使線程間的變量互不干擾。
ThreadLocal實現
每個線程內部都會維護一個ThreadLocalMap對象,該map的key為存儲的變量對象,value為對象的值。
當調用ThreadLocal的set()方法時,如果map非空,則將ThreadLocal對象和值存入map中;如果map為空,則新建ThreadLocalMap
調用get()方法時,則先獲取當前線程的ThreadLocal對象,再根據對象獲取對應的value值。
*具體實現邏輯更為復雜,詳細實現可以參考https://www.jianshu.com/p/98b68c97df9b
ThreadLocal使用案例
/** * 通過ThreadLocal保存各自線程中的變量 * Created by xuec on 2019/3/4. */ public class Test { //初始化變量 private ThreadLocal<Long> longLocal = new ThreadLocal<>(); private ThreadLocal<String> stringLocal = new ThreadLocal<>(); /** * 為變量賦值 */ private void set() { longLocal.set(Thread.currentThread().getId()); stringLocal.set(Thread.currentThread().getName()); } /** * 獲取變量 * @return Long型變量 */ private Long getLong() { return longLocal.get(); } /** * 獲取變量 * @return String型變量 */ private String getString() { return stringLocal.get(); } public static void main(String[] args) throws InterruptedException { final Test test = new Test(); //在主線程中賦值 test.set(); System.out.println("main-id: " + test.getLong()); System.out.println("main-name: " + test.getString()); //新建線程 final Thread thread1 = new Thread() { @Override public void run() { //在線程1中賦值 test.set(); //打印線程1中的值 System.out.println("Thread1-id: " + test.getLong()); System.out.println("Thread1-name: " + test.getString()); } }; thread1.start(); thread1.join(); //再次打印變量 System.out.println("main-id: " + test.getLong()); System.out.println("main-name: " + test.getString()); } }
輸出:
main-id: 1 main-name: main Thread1-id: 11 Thread1-name: Thread-0 main-id: 1 main-name: main
從結果可以看出,main線程和Thread1線程中,longLocal和stringLocal保存的值都不一樣。
ThreadLocal應用場景
ThreadLocal主要應用於數據庫連接、線程會話等場景,每個線程都保持獨立的會話。如果是變量是全局共享的,則並不適用於ThreadLocal。