java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java ThreadLocal核心知识点

Java ThreadLocal核心知识点源码解析

作者:时艰.

hreadLocal在Java多线程编程中常被用来保证每个线程都有其自己的变量副本,避免线程安全问题,而弱引用是Java内存管理中的一个重要概念,用于在垃圾回收时释放对象,这篇文章主要介绍了Java ThreadLocal核心知识点源码解析的相关资料,需要的朋友可以参考下

一、ThreadLocal 核心概念

1. 定义

ThreadLocal 是 Java 提供的线程局部变量工具类,用于在多线程环境下为每个线程维护独立的变量副本,确保线程安全与数据隔离。变量通常声明为 private static 类型,用于关联线程上下文。

2. 核心特性

3. 与 synchronized 的区别

对比维度synchronizedThreadLocal
实现原理以时间换空间,单变量 + 线程排队访问以空间换时间,线程私有变量副本
核心目标多线程共享资源的同步控制多线程数据隔离,独立访问
并发性能串行执行,性能开销较大并行执行,无同步开销
适用场景多线程需修改共享资源多线程需独立变量副本

二、ThreadLocal 基本使用

1. 核心方法

方法声明功能描述
ThreadLocal<T>()构造 ThreadLocal 实例
void set(T value)设置当前线程的变量副本
T get()获取当前线程的变量副本
void remove()移除当前线程的变量副本
protected T initialValue()返回变量初始值(默认 null,可重写)

2. 经典使用案例

public class ThreadLocalDemo {
    // 声明 ThreadLocal 变量(通常 static)
    private static ThreadLocal<String> threadLocal = new ThreadLocal<String>(){
        // 重写初始值方法(可选)
        @Override
        protected String initialValue() {
            return "默认值";
        }
    };

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            Thread thread = new Thread(() -> {
                // 设置当前线程的变量值
                threadLocal.set(Thread.currentThread().getName() + "的数据");
                // 获取当前线程的变量值
                System.out.println(Thread.currentThread().getName() + "--->" + threadLocal.get());
                // 移除变量(避免内存泄漏)
                threadLocal.remove();
            });
            thread.setName("线程" + i);
            thread.start();
        }
    }
}

输出结果(线程隔离,数据独立):

线程0--->线程0的数据
线程1--->线程1的数据
线程2--->线程2的数据
线程3--->线程3的数据
线程4--->线程4的数据

三、ThreadLocal 内部结构

1. 设计演进

2. 核心结构

3. 设计优势

四、核心方法源码解析

1. set () 方法

public void set(T value) {
    // 1. 获取当前线程
    Thread t = Thread.currentThread();
    // 2. 获取线程的 ThreadLocalMap
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        // 3. 存在则设置键值对(key:当前ThreadLocal实例)
        map.set(this, value);
    } else {
        // 4. 不存在则创建Map并初始化
        createMap(t, value);
    }
}

// 获取线程的 ThreadLocalMap(Thread类的 threadLocals 属性)
ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}

// 创建 ThreadLocalMap 并添加第一个条目
void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}

2. get () 方法

public T get() {
    // 1. 获取当前线程
    Thread t = Thread.currentThread();
    // 2. 获取线程的 ThreadLocalMap
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        // 3. 查找当前ThreadLocal对应的Entry
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            // 4. 存在则返回value
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    // 5. 不存在则初始化(调用initialValue())
    return setInitialValue();
}

// 初始化方法
private T setInitialValue() {
    T value = initialValue(); // 默认返回null,可重写
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        map.set(this, value);
    } else {
        createMap(t, value);
    }
    return value;
}

3. remove () 方法

public void remove() {
    // 1. 获取当前线程的 ThreadLocalMap
    ThreadLocalMap m = getMap(Thread.currentThread());
    if (m != null) {
        // 2. 移除当前ThreadLocal对应的条目
        m.remove(this);
    }
}

4. initialValue () 方法

protected T initialValue() {
    // 默认返回null,子类可重写以设置非null初始值
    return null;
}

五、ThreadLocalMap 深度解析

1. 基本结构

2. Entry 结构

static class Entry extends WeakReference&lt;ThreadLocal&lt;?&gt;&gt; {
    // 变量副本(强引用)
    Object value;

    // key为ThreadLocal实例(弱引用)
    Entry(ThreadLocal&lt;?&gt; k, Object v) {
        super(k);
        value = v;
    }
}

3. 内存泄漏问题

(1)核心概念

(2)泄漏原因分析

(3)关键前提(两者缺一不可)

(4)弱引用的作用

(5)解决方案

4. 哈希冲突解决

六、ThreadLocal 典型应用场景

1. Spring 事务管理

2. 其他场景

总结 

到此这篇关于Java ThreadLocal核心知识点的文章就介绍到这了,更多相关Java ThreadLocal核心知识点内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文