java 本地线程_ThreadLocal = 本地线程?

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 17:55   608   0

一、定义

ThreadLocal是JDK包提供的,从名字来看,ThreadLocal意思就是本地线程的意思。

1.1 是什么?

要想知道他是个啥,我们看看ThreadLocal的源码(基于JDK 1.8)中对这个类的介绍:

This class provides thread-local variables. These variables differ from

their normal counterparts in that each thread that accesses one (via its

{@code get} or {@code set} method) has its own, independently initialized

copy of the variable. {@code ThreadLocal} instances are typically private

static fields in classes that wish to associate state with a thread (e.g.,

a user ID or Transaction ID).

大致能够总结出:

TreadLocal可以给我们提供一个线程内的局部变量,而且这个变量与一般的变量还不同,它是每个线程独有的,与其他线程互不干扰的;

ThreadLocal 与普通变量的区别在于:每个使用该变量的线程都会初始化一个完全独立的实例副本。ThreadLocal 变量通常被private static修饰。当一个线程结束时,它所使用的所有 ThreadLocal 相对的实例副本都会被回收;

简单说ThreadLocal就是一种以空间换时间的做法,在每个Thread里面维护了一个ThreadLocal.ThreadLocalMap,把数据进行隔离,每个线程的数据不共享,自然就没有线程安全方面的问题了.

1.2 示例

一言不合上代码!

//创建ThreadLocal变量

private static ThreadLocal localParam = new ThreadLocal<>();

@Test

public void threadLocalDemo() {

//创建2个线程,分别设置不同的值

new Thread(() -> {

localParam.set("Hello 风尘博客!");

//打印当前线程本地内存中的localParam变量的值

log.info("{}:{}", Thread.currentThread().getName(), localParam.get());

}, "T1").start();

new Thread(() -> {

log.info("{}:{}", Thread.currentThread().getName(), localParam.get());

}, "T2").start();

}

结果:

... T1:Hello 风尘博客!

... T2:null

打印结果证明,T1线程中设置的值无法在T2取出,证明变量ThreadLocal在各个线程中数据不共享。

1.3 ThreadLocal的API

ThreadLocal定义了四个方法:

get():返回此线程局部变量当前副本中的值;

set(T value):将线程局部变量当前副本中的值设置为指定值;

initialValue():返回此线程局部变量当前副本中的初始值;

remove():移除此线程局部变量当前副本中的值。

set()和initialValue()区别

名称

set()

initialValue()

定义

为这个线程设置一个新值

该方法用于设置初始值,并且在调用get()方法时才会被触发,所以是懒加载。但是如果在get()之前进行了set()操作,这样就不会调用

区别

如果对象生成的时机不由我们控制的时候使用 set() 方式

对象初始化的时机由我们控制的时候使用initialValue() 方式

二、实现原理

ThreadLocal有一个特别重要的静态内部类ThreadLocalMap,该类才是实现线程隔离机制的关键。

每个线程的本地变量不是存放在ThreadLocal实例里面,而是存放在调用线程的threadLocals变量里面,也就是说:ThreadLocal类型的本地变量存放在具体的线程内存空间中。

ThreadLocal.ThreadLocalMap threadLocals = null;

ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

Thread类中有两个ThreadLocalMap类型的变量,分别是threadLocals和inheritableThreadLocals,而ThreadLocalMap是一个定制化的Hashmap,专门用来存储线程本地变量。在默认情况下,每个线程中的这两个变量都为null,只有当前线程第一次调用ThreadLocal的set()或者get()方法时才会创建它们。

925b3d2796f99eed811b0899a0571e93.png

ThreadLocal就是一个工具壳,它通过set()方法把value值放入调用线程的threadLocals里面并存放起来,当调用线程调用它的get()方法时,再从当前线程的threadLocals变量里面将其拿出来使用。

如果调用线程一直不终止,那么这个本地变量会一直存放在调用线程的threadLocals变量里面,所以当不需要使用本地变量时可以通过调用ThreadLocal变量的remove()方法,从当前线程的threadLocals里面删除该本地变量。

另外Thread里面的threadLocals被设计为Map结构是因为每个线程可以关联多个ThreadLocal变量。

原理小结

每个Thread维护着一个ThreadLocalMap的引用;

ThreadLocalzǖJ3.jGРZWR2z/(> Z(no*r(

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP