ThreadLocal原理
ThreadLocal介绍
ThreadLocal是JDK包提供的,它提供了线程本地变量,也就是如果你创建了一个ThreadLocal变量,
那么访问这个变量的每个线程都会有这个变量的一个本地副本。当多个线程操作这个变量时,
实际操作的是自己本地内存里面的变量,从而避免了线程安全问题。
基本使用

threadOne:threadOne local variable
threadOne remove after :threadOne local variable
threadTwo:threadTwo local variable
threadTwo remove after :threadTwo local variable
- 线程One中的代码通过set方法设置了local的值,这其实设置的是线程One本地内存中的一个副本
- 这个副本线程Two是访问不了的。然后代码调用了print函数,代码通过get函数获取了当前线程(线程One)本地内存中local的值。
ThreadLocal实现原理

- Thread类中有一个
threadLocals和一个inheritableThreadLocals,它们都是ThreadLocalMap类型的变量,而ThreadLocalMap是一个定制化的Hashmap。 - 在默认情况下,每个线程中的这两个变量都为
null,只有当前线程第一次调用ThreadLocal的set或者get方法时才会创建它们。 - 其实每个线程的本地变量不是存放在
ThreadLocal实例里面,而是存放在调用线程的threadLocals变量里面。也就是说,ThreadLocal类型的本地变量存放在具体的线程内存空间中。 - ThreadLocal就是一个工具壳,它通过set方法把value值放入调用线程的threadLocals里面并存放起来,当调用线程调用它的get方法时,再从当前线程的threadLocals变量里面将其拿出来使用。
- 如果调用线程一直不终止,那么这个本地变量会一直存放在调用线程的threadLocals变量里面,所以当不需要使用本地变量时可以通过调用ThreadLocal变量的remove方法,从当前线程的threadLocals里面删除该本地变量。

ThreadLocal中的set,get,remove方法

首先获取调用线程,然后使用当前线程作为参数调用getMap(t)方法,getMap(Thread t)的代码如下
set()方法
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
- 可以看到,
getMap(t)的作用是获取线程自己的变量threadLocals,threadlocal变量被绑定到了线程的成员变量上。 - 如果
getMap(t)的返回值不为空,则把value值设置到threadLocals中,也就是把当前变量值放入当前线程的内存变量threadLocals中。 threadLocals是一个HashMap结构,其中key就是当前ThreadLocal的实例对象引用,value是通过set方法传递的值。- 如果
getMap(t)返回空值则说明是第一次调用set方法,这时创建当前线程的threadLocals变量。下面来看createMap(t, value)做什么。
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
- 它创建当前线程的threadLocals
get()方法

- 代码首先获取当前线程实例,如果当前线程的threadLocals变量不为null,则直接返回当前线程绑定的本地变量,否则执行代码进行初始化。
setInitialValue()的代码如下。

- 如果当前线程的
threadLocals变量不为空,则设置当前线程的本地变量值为null,否则调用createMap方法创建当前线程的createMap变量。
remove()

- 如果当前线程的
threadLocals变量不为空,则删除当前线程中指定ThreadLocal实例的本地变量。
总结
- 在每个线程内部都有一个名为
threadLocals的成员变量,该变量的类型为HashMap,其中key为我们定义的ThreadLocal变量的this引用,value则为我们使用set方法设置的值。 - 每个线程的本地变量存放在线程自己的内存变量
threadLocals中,如果当前线程一直不消亡,那么这些本地变量会一直存在,所以可能会造成内存溢出 - 因此使用完毕后要记得调用
ThreadLocal的remove方法删除对应线程的threadLocals中的本地变量。
由于时间有限,写的不好请见谅,理解万岁(:


浙公网安备 33010602011771号