美文网首页
ThreadLocal介绍

ThreadLocal介绍

作者: 一直在路上_求名 | 来源:发表于2020-06-23 01:13 被阅读0次

ThreadLocal 能做什么

ThreadLocal 是 JDK 提供的一个工具类,它可以为每个使用它的线程创建一个线程本地的副本,从而能保证多个线程在访问时的安全问题。当多个线程在使用这个变量时,其实是在使用自己线程本地内存的变量,由于是线程级别的,因此就能完全避免多个线程访问时,资源竞争的安全问题。

ThreadLocal 的原理

要讲解 ThreadLocal 的原理,我们首先需要看 JDK 的源码,了解了 ThreadLocal 类的主要方法实现就能理解其原理了。使用 ThreadLocal 时主要就是调用它的两个方法即 get 方法和 set 方法,下面直接贴出他们的源码。

首先看 set 方法:

public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

由于 ThreadLocal 是一个带泛型的类,所以在创建 ThreadLocal 对象时,需要指定对应的泛型而 set 方法的入参就是定义的泛型对象;
接下来看具体的逻辑:
1首先创建了一个当前调用 set 方法的线程实例对象;
2、调用 getMap 方法,入参为当前线程的实例对象,返回一个当前线程对象的 threadLocals 属性值,threadLocals 是Thread 类的一个属性,也就是说 Java 的所有线程对象都有这个属性,这个属性是一个 ThreadLocalMap 对象(ThreadLocalMap 其实就是一个简化版的 HashMap);
3、如果返回的 ThreadLocalMap 为 null(threadLocals 属性的默认值就是 null),则会创建一个 ThreadLocalMap 对象,会调用createMap 方法;
4、createMap 方法接收两个入参,一个为 当前调用线程的实例对象,一个为 firstValue(默认 firstValue 为 null)因此这个方法会创建一个 key 为当前调用线程实例,value 为当前 set 方法传入的值 的ThreadLocalMap 对象,并将这个对象赋值给当前线程实例的 threadLocals 属性;
总结:要想了解 set 方法,就需要了解 threadLocals 属性,简单理解它就是一个 key 为当前线程实例对象的 HashMap;set 方法就是把 set 的入参设置到这个 hashMap 的 value 中的过程;

接下来看 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();
    }
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;
    }

其实 get 方法和 set 方法一样,本质上都是操作当前线程实例的 threadLocals 属性,只是 get 方法是获取该属性的 value 值;
接下来看具体的逻辑:
1、前面的两个操作和 set 方法一样,获取当前调用线程实例的 threadLocals 属性值;
2、如果不为空则直接返回当前属性值的 value 值;
3、如果为空则为当前线程实例初始化一个 value 值为空的 threadLocals 属性(initialValue 方法的返回值为 null);

原理总结

1、通过以上源码介绍,其实 ThreadLocal 是一个带泛型的类,使用的时候就是调用它的 get 方法和它的 set 方法;
2、这两个方法的本质就是操作当前调用线程实例的 threadLocals 属性值;
3、threadLocals 属性是一个 Thread LocalMap 对象,这个对象就是一个简单的 HashMap,而它的 key 为当前线程的实例对象,value 为某个需要被共享的变量值;
4、由于这个值是放在当前线程实例的一个 Map 中,因此多个线程访问的时候是访问自己本地的变量,因此不可能有多线程安全访问的问题;

ThreadLocal 应用 Demo

先上代码

public static void main(String[] args) {
        ThreadLocal<String> stringThreadLocal = new ThreadLocal<>();
        stringThreadLocal.set("main threadLocal");
        System.out.println("main threadLocal value:"+stringThreadLocal.get());
        Thread threadA = new Thread(() -> {
            stringThreadLocal.set("threadA threadLocal");
            System.out.println("threadA threadLocal value:" + stringThreadLocal.get());
        });
        Thread threadB = new Thread(() -> {
            stringThreadLocal.set("threadB threadLocal");
            System.out.println("threadB threadLocal value:" + stringThreadLocal.get());
        });
        threadA.start();
        threadB.start();
    }

结果

main threadLocal value:main threadLocal
threadA threadLocal value:threadA threadLocal
threadB threadLocal value:threadB threadLocal

上面是对 ThreadLocal 最简单的使用,虽然对 ThreadLocal 来说是一个对象,并且是被三个线程共同访问,正常情况下由于多线程的问题一定会表现为结果不可预知;但是由于 ThreadLocal 的特性,是当前线程的本地副本设置属性值,因此不会出现多线程安全的问题;可以用它来记录一下上下文的一内容信息,或者用来设置一个日志的唯一标识 uuid 等,来标识当前线程的执行日志,方便查找问题。

相关文章

  • 大话 ThreadLocal

    概述 ThreadLocal 介绍 ThreadLocal 关键方法讲解 ThreadLocalMap 内部类介绍...

  • ThreadLocal原理介绍以及内存泄漏分析

    ThreadLocal简单介绍 ThreadLocal同ReentrantLock,CyclicBarrier等都...

  • Looper场景ThreadLocal原理分析

    ThreadLocal介绍 ThreadLocal支持泛型,ThreadLocal,T代表的是线程本地变量,...

  • 聊一聊我眼中的ThreadLocal(面试题形式总结)

    这篇总结一下 ThreadLocal,主要的议题有: ThreadLocal 介绍 ThreadLocal 实现原...

  • ThreadLocal介绍

    ThreadLocal简介 ThreadLocal是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数...

  • ThreadLocal介绍

    我们在说明handler原理和AsyncTask原理的时候都提到了ThreadLocal,当时没有细说,现在来介绍...

  • ThreadLocal介绍

    ThreadLocal,顾名思义,其存储的内容是线程本地的,私有的,我们常用来存储和维护一些资源或者变量,以避免线...

  • ThreadLocal介绍

    ThreadLocal 能做什么 ThreadLocal 是 JDK 提供的一个工具类,它可以为每个使用它的线程创...

  • 介绍ThreadLocal

    1、概览 在本文中,我们将研究下ThreadLocal。ThreadLocal为我们提供了为当前线程单独保存数据的...

  • ThreadLocal介绍

    1. 简单使用 可以看到,同一个线程中设置完userId,在线程中的其他地方可以读取出来使用 2. 实现原理 我们...

网友评论

      本文标题:ThreadLocal介绍

      本文链接:https://www.haomeiwen.com/subject/mlvdxktx.html