首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 並發核心:ThreadLocal 線程局部變量原理、用法與最佳實踐

     編輯:Java 綜合教學

Java 並發核心:ThreadLocal 線程局部變量原理、用法與最佳實踐

1. ThreadLocal 簡述

ThreadLocal 實例通常作為 private static 字段出現在類中,用於關聯線程。它是線程級別的局部變量,關鍵點:

  • A:多線程訪問同一 ThreadLocal 實例時,為每個線程提供獨立的變量副本,線程間互不影響。
  • B:從線程角度看,目標變量如同線程本地變量,這也是「Local」含義。

2. 核心方法詳解

ThreadLocal<T> 僅有四個方法:

  1. void set(T value):設置當前線程的變量副本。
  2. T get():獲取當前線程的變量副本。
  3. void remove():移除當前線程的變量副本,減少內存佔用(JDK 5.0 新增)。線程結束時局部變量自動被 GC 回收,顯式調用非必須但可加速回收。
  4. protected T initialValue():延遲加載方法,默認返回 null,通常通過匿名內部類重寫指定初始值。

3. 實戰示例

package com.test;

public class ThreadMain {
    // ① 匿名內部類重寫 initialValue() 指定初始值
    private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>() {
        @Override
        protected Integer initialValue() {
            return 0;
        }
    };

    // ② 獲取下一個序列值
    public int getNextNum() {
        seqNum.set(seqNum.get() + 1);
        return seqNum.get();
    }

    public static void main(String[] args) {
        ThreadMain sn = new ThreadMain();
        // ③ 3個線程共享 sn,各自產生序列號
        TestClient t1 = new TestClient(sn);
        TestClient t2 = new TestClient(sn);
        TestClient t3 = new TestClient(sn);
        t1.start();
        t2.start();
        t3.start();
    }

    private static class TestClient extends Thread {
        private ThreadMain sn;
        public TestClient(ThreadMain sn) { this.sn = sn; }
        @Override
        public void run() {
            for (int i = 0; i < 3; i++) {
                // ④ 每個線程打印 3 個序列值
                System.out.println("thread[" + Thread.currentThread().getName() + "] --> sn[" + sn.getNextNum() + "]");
            }
        }
    }
}

輸出結果:

thread[Thread-0] --> sn[1]
thread[Thread-2] --> sn[1]
thread[Thread-1] --> sn[1]
thread[Thread-2] --> sn[2]
thread[Thread-0] --> sn[2]
thread[Thread-2] --> sn[3]
thread[Thread-1] --> sn[2]
thread[Thread-1] --> sn[3]
thread[Thread-0] --> sn[3]

每個線程擁有獨立的 seqNum 副本,從 1 開始遞增,互不干擾。

4. 實現機制簡析

深度源碼分析暫不展開,參考:https://www.importnew.com/17849.html

get() 方法源碼片段:

ThreadLocal get方法源碼

5. 總結與最佳實踐

  • ThreadLocal 通常聲明為 static。若不斷創建且未調用 remove(),會導致內存洩漏,尤其在高並發 Web 容器中。
  • 處理線程局部變量時,ThreadLocal 比 synchronized 更簡單、方便,並發性能更高(空間換時間,無鎖)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved